2012-12-10 35 views
13

可能重复:
What is the purpose of the expression “new String(…)” in Java?为什么String类有复制构造函数?

如果一成不变的类的对象副本将等于原稿那么为什么在String类在Java中有一个拷贝构造函数?这是一个错误还是这个实现背后有一个原因? 在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) { 
.... 
....} 
+6

这不是“过于本地化”,这是一个很好的问题,适用于稍后发现它的人,提供非常有用的信息答案。 –

+3

请参阅[本](http://stackoverflow.com/a/465682/1037210)回答。 – Lion

+0

请注意,所提到的类似问题的答案现在可能已被部分废弃。 –

回答

10

的主要原因复制字符串是“修剪包袱”,即修剪底层字符数组只什么是必要的。

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

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; 

这是很多开发者忘记了,是重要的,因为一个小的字符串可能会阻止:

我用,“修剪包袱”的表达,从字符串拷贝构造函数的源代码取一个更大的字符阵列的garbaging。看到这个相关的问题,我已经指出:Java not garbage collecting memory。许多开发人员认为,比起Java设计人员使用C编程人员熟悉的旧优化技巧的决定,事实上,这样做更有害无益。我们很多人都知道它,因为我们被它咬了,并且必须查看Sun的源代码来了解发生了什么......

正如Marko指出的那样(参见下面的注释),在OpenJDK中,从java 7 Update 6开始,substring不再共享char数组,因此String(String)构造函数无用。但它仍然很快(事实上甚至更快),并且由于此更改尚未传播给所有虚拟机(并且可能不是所有客户),所以我建议在旧的行为证明它合理时使用new String(substring)来保持此最佳做法。

+5

...它从OpenJDK 7 Update 6中消失了。通过'substring','trim'等没有更多的结构共享。 –

+0

@Marko你能指出你提到的更新的来源吗?我没有意识到这一重要变化。 –

+3

[参考这里](http://hg.openjdk.java.net/jdk7u/jdk7u6/jdk/file/8c2c5d63a17e/src/share/classes/java/lang/String.java)我已经拥有它的书签,它是自从我从Jon Skeet那里了解到它之后,它一直是大众需求! –

相关问题