为什么String类有复制构造函数?

可能重复:
Java中表达式“new String(…)”的目的是什么?

如果不可变类对象副本等于原始副本那么为什么Java中的String类有一个复制构造函数? 这是一个错误还是这个实施背后的原因? 在Java文档中,它被指定为:

 /** * Initializes a newly created {@code String} object so that it represents * the same sequence of characters as the argument; in other words, the * newly created string is a copy of the argument string. Unless an * explicit copy of {@code original} is needed, use of this constructor is * unnecessary since Strings are immutable. * * @param original * A {@code String} */ public String(String original) { .... ....} 

复制字符串的主要原因是“修剪行李” ,即将基础字符数组修剪为仅需要的内容。

底层char数组可能过大,因为当你通过调用substring创建一个字符串时,char数组可以在新的字符串实例和源字符串实例之间共享; 偏移量指向第一个字符,并包含长度。

我使用的表达式“修剪行李”取自String复制构造函数的源代码:

  164 public String(String original) { 165 int size = original.count; 166 char[] originalValue = original.value; 167 char[] v; 168 if (originalValue.length > size) { 169 // The array representing the String is bigger than the new 170 // String itself. Perhaps this constructor is being called 171 // in order to trim the baggage, so make a copy of the array. 172 int off = original.offset; 173 v = Arrays.copyOfRange(originalValue, off, off+size); 174 } else { 175 // The array representing the String is the same 176 // size as the String, so no point in making a copy. 177 v = originalValue; 178 } 179 this.offset = 0; 180 this.count = size; 181 this.value = v; 

这是许多开发人员忘记并且很重要的事情,因为一个小字符串可能会阻止更大的char数组的吞噬。 看到这个相关的问题,我已经指出了这一点: Java不是垃圾收集内存 。 许多开发人员认为,而不是Java设计师决定使用C编码器所熟悉的旧优化技巧,实际上弊大于利。 我们中的许多人都知道它,因为我们被它咬了,并且必须查看Sun的源代码以了解发生的事情……

正如Marko指出的那样(见下面的评论),在OpenJDK中,从java 7 Update 6开始, substring不再共享char数组,因此String(String)构造函数是无用的。 但它仍然很快(实际上甚至更快)并且由于此更改尚未传播到所有VM(可能不是所有客户),我建议保持这种最佳做法,以便在旧时使用new String(substring)行为certificate了这一点。