1

文字列定数で文字列のインターンメソッドを使用する必要がある場合にこれを読みましたが、文字列 == ではまだあまり明確ではありません intern() と比較してください。いくつかの例があります。誰かがこれをよりよく理解するのを手伝ってくれますか?

String s1 = "abc";
String s2 = "abc";
String s3 = "abcabc";
String s4 = s1 + s2;

System.out.println(s3 == s4);                            // 1. why false ?
System.out.println(s3 == s4.intern());                   // 2. why true ?
System.out.println(s4 == s1 + s2);                       // 3. why false ?
System.out.println(s4 == (s1 + s2).intern());            // 4. why false ?
System.out.println(s4.intern() == (s1 + s2).intern());   // 5. why true ?
4

3 に答える 3

3

ここにはそれを説明する非常に多くの回答がありますが、別の回答をさせてください。

文字列は、クラスがロードされ、文字列がリテラルまたはコンパイル時の定数であった場合にのみ、文字列リテラル プールにインターンされます。それ以外の場合は、文字列を呼び出す場合のみ.intern()。次に、この文字列のコピーがプールにリストされ、返されます。他のすべての文字列の作成はインターンされません。文字列連結 ( +) は、コンパイル時の定数式でない限り、新しいインスタンスを生成しています*。

まず第一に、決して使用しないでください。それを理解していない場合は、使用しないでください。を使用し.equals()ます。比較のために文字列をインターンすることは、思ったよりも遅く、ハッシュテーブルを不必要に埋める可能性があります。特に、内容が大きく異なる文字列の場合。

  1. s3 は定数プールの文字列リテラルであるため、インターンされます。s4 は、インターンされた定数を生成しない式です。
  2. s4 をインターンすると、s3 と同じコンテンツを持つため、同じインスタンスになります。
  3. s4 と同じ、式は定数ではありません
  4. s1+s2 をインターンすると、s3 のインスタンスが取得されますが、s4 はまだ s3 ではありません。
  5. s4 をインターンする場合、s3 と同じインスタンスです

いくつかの質問:

System.out.println(s3 == s3.intern());       // is true
System.out.println(s4 == s4.intern());       // is false
System.out.println(s1 == "abc");             // is true
System.out.println(s1 == new String("abc")); // is false

* コンパイル時の定数は、連結の両側にリテラルを含む式 ( など"a" + "bc") にすることができますが、定数またはリテラルから初期化された最終的な文字列変数にすることもできます。

    final String a = "a";
    final String b = "b";
    final String ab = a + b;
    final String ab2 = "a" + b;
    final String ab3 = "a" + new String("b");
    System.out.println("ab == ab2 should be true:  " + (ab == ab2));
    System.out.println("a+b == ab should be true:  " + (a+b == ab));
    System.out.println("ab == ab3 should be false: " + (ab == ab3));
于 2015-10-24T22:41:10.277 に答える
0

知っておくべきことの 1 つは、文字列は Java のオブジェクトであることです。変数 s1 ~ s4 は、保存したテキストを直接指していません。これは、RAM 内のテキストを見つける場所を示す単なるポインターです。

  1. 実際のテキストではなくポインターを比較するため、これは誤りです。テキストは同じですが、これらの 2 つの文字列は 2 つの完全に異なるオブジェクトです。つまり、異なるポインターを持っています。コンソールで s1 と s2 を印刷してみてください。

  2. Java は文字列に関する最適化を行うため、その通りです。JVM が 2 つの異なる文字列が同じテキストを共有していることを検出した場合、それらは「文字列リテラル プール」と呼ばれるものになります。s3 と s4 は同じテキストを共有するため、「文字列リテラル プール」内の同じスロットにも保存されます。inter() メソッドは、リテラル プール内の文字列への参照を取得します。

  3. 1 と同じです。2 つのポインターを比較します。テキストコンテンツではありません。

  4. 私の知る限り、追加された値はプールに保存されません

  5. 2 と同じです。同じテキストが含まれているため、文字列リテラル プールに格納され、同じスロットを共有します。

于 2015-10-24T22:42:54.537 に答える
0

まず、s1、s2、および s3 は、リテラルで宣言されているため、宣言された時点でインターン プールにあります。s4 は、最初からインターン プールにはありません。これは、インターンプールが最初にどのように見えるかです:

"abc" (s1, s2)
"abcabc" (s3)
  1. s3 はインターン プールにあるため、s4 は s3 と一致しませんが、s4 は一致しません。
  2. intern() は s4 で呼び出されるため、プール内で "abcabc" に等しい他の文字列を探し、それらを 1 つのオブジェクトにします。したがって、s3 と s4.intern() は同じオブジェクトを指します。
  3. ここでも、2 つの文字列を追加するときに intern() が呼び出されないため、intern() プールから一致しません。
  4. s4 はインターン プールにないため、(s1 + s2).intern() のオブジェクトと一致しません。
  5. これらは両方ともインターンされているため、インターンプールを調べてお互いを見つけます。
于 2015-10-24T22:49:27.207 に答える