2012-12-10 11 views
13

可能性の重複:
What is the purpose of the expression “new String(…)” in Java?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) { 
.... 
....} 
+6

これはあまりにもローカライズされているわけではありません。後で見つけた方には、非常に有益な回答があります。 –

+3

[this](http://stackoverflow.com/a/465682/1037210)の回答を参照してください。 – Lion

+0

前述の類似の質問に対する回答は、おそらく部分的に廃止されたと考えられる可能性があることに注意してください。 –

答えて

10

、それは必要なものだけに基礎となるchar配列をトリミングすることです。

substringを呼び出して文字列を作成すると、新しい文字列インスタンスとソース文字列インスタンスの間でchar配列を共有できるため、基本となるchar配列は主に大きすぎる可能性があります。最初の文字と長さのオフセット点が含まれます。

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; 

これは、多くの開発者が忘れて何かで、小さな文字列はなくなる可能性があるために重要である:

表現私は「荷物をトリム」、使用は、文字列のコピーコンストラクタのソースコードから取られますより大きな文字列のガーベージ。私がすでに指摘しているこの関連の質問を参照してください:Java not garbage collecting memory。多くの開発者は、JavaのデザイナーがCのコーダーに慣れ親しんだこの古い最適化の仕組みを使用するという決定よりも、実際には利益よりも害があると考えています。私たちの多くは、それを知っていて、Sunのソースコードを調べて、何が起こったのかを理解する必要がありました。

Markoが指摘するように(以下のコメントを参照)、OpenJDKではJava 7 Update 6 substringはchar配列をもう共有しません。したがって、String(String)コンストラクタは役に立たなくなります。しかし、それはまだ高速です(実際にはもっと速いです)。そして、この変更がすべてのVM(おそらくすべてのお客様ではない)に伝わっていないため、このベストプラクティスを維持して、古い動作が正当化していたときに使用することをお勧めします。 。

+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からそれについて学んだので、今まで人気のある需要になっていました! –

関連する問題