为什么私有包String构造函数(int,int,char [])已被删除?

时间:2015-06-09 18:06:06

标签: java string memory-leaks

在Java 6中,有一个包私有构造函数,用于返回一个新的String,其偏移量已被更改。

643     // Package private constructor which shares value array for speed.
644     String(int offset, int count, char value[]) {
645         this.value = value;
646         this.offset = offset;
647         this.count = count;
648     }

它已在Java 7中被标记为已弃用并在Java 8中被删除。我依赖于一些反复调用subSequence的API,直到遇到性能问题。

深入研究代码我看到subSequence在Java 6中使用了这个构造函数。但是现在,它使用另一个复制底层数组并从所需的结束偏移量开始,从而使它成为一个O(1)操作到O(n)。

将有问题的电话更换为subSequence,使性能提高了10倍。

我想知道为什么要做出这样的改变。我唯一想到的是它可能会造成潜在的内存泄漏,例如:

String veryLargeString = ....;
String target = veryLargeString.substring(0, 10);
//assume I don't need anymore veryLargeString at this point

此时,底层char数组不能是GC,因为它仍然被目标String使用。因此,你在内存中有一个大数组,但你只需要它的前10个值。

这是唯一的好用例还是有其他原因导致此构造函数被删除?

1 个答案:

答案 0 :(得分:3)

是的,Stringchanged significantly in Java 7 update 6 - 现在单独的String个对象永远不会共享基础char[]。这绝对是一个权衡:

  • 字符串不再需要维护偏移和长度(每个实例保存两个字段;不是很多,但是每个字符串...)
  • 一个小字符串最终无法保持巨大的char[]活着(根据您的帖子)
  • ...但以前便宜的操作现在最终会创建副本

在某些用例中,以前的代码可以更好地工作 - 在其他用例中,新代码可以更好地工作。不幸的是,这听起来像你在第一阵营。我无法想象这个决定是轻率的,但是 - 我怀疑已经针对不同的常见工作负荷做了很多测试。