如果我们看一下String#substring
方法实现:
new String(offset + beginIndex, endIndex - beginIndex, value);
我们看到使用相同原始内容(参数 char []值)创建了一个新字符串。
因此,解决方法是使用new String(toto.substring(...))
删除对原始char []值的引用,并使其符合GC条件(如果不存在更多引用)。
我想知道是否有一个特殊的原因来解释这个实现。为什么该方法不会创建新的较短的字符串以及为什么她保留完整的原始值呢?
另一个相关的问题是:在处理子字符串时我们是否总是使用new String(...)
?
答案 0 :(得分:2)
因为String
是immutable类
另见
答案 1 :(得分:2)
我想知道是否有一个特殊的原因来解释这个实现。为什么该方法不会创建新的较短的字符串以及为什么她保留完整的原始值呢?
因为在大多数用例中,substring()
以这种方式工作的速度更快。至少,这就是Sun / Oracle的经验测量所表明的。通过这样做,实现避免了分配后备阵列并将字符复制到数组。
如果您必须复制String以避免内存泄漏问题,那么这只是非优化。在绝大多数情况下,子串在相对较短的时间内变成垃圾,并且没有长期的内存泄漏。
假设,Java设计人员可以提供两个版本的substring
,一个版本当前行为,另一个版本创建具有自己的支持数组的String。但这会鼓励开发人员浪费思考使用哪个版本的脑循环。然后就是基于子串的实用程序方法的问题......比如Pattern
/ Matcher
类。所以我认为他们没有这样做是件好事。
答案 2 :(得分:1)
这种实施的原因是效率。通过指向与原始字符串相同的char[]
,不需要复制任何数据。
这确实有一个缺点,因为你已经暗示过自己。如果原始字符串很长并且您只想获取它的一小部分,并且之后不再需要原始字符串,那么仍然会引用完整的原始数组,并且不能对其进行垃圾回收。您已经知道如何避免这种情况 - 执行new String(original.substring(...))
。
我们在处理子字符串时应该总是使用
new String(...)
吗?
不,不是总是。只有当你知道它可能会导致问题。在许多情况下,引用原始char[]
而不是复制数据更有效。