7
        String s1 = new String("string");
        String s2 = new String("string");

        String s3 = "string";
        String s4 = "string";

        System.out.println(s1 == s2);      //FALSE
        System.out.println(s2.equals(s1)); //TRUE

        System.out.println(s3 == s4);      //TRUE
        System.out.println(s3.equals(s4)); //TRUE

s1の作成との作成の違いは何s3ですか? 私にお知らせください

String には String オブジェクトしかないのに、なぜこの 2 つを異なる方法で扱うのでしょうか。s1 と s2 のメモリ アドレスは異なりますが、s3 と s4 のメモリ アドレスは同じです。new演算子に基づいて機能するのはなぜですか。

4

4 に答える 4

7

Java ソース コード内のString文字列リテラルを表すオブジェクトは、Stringそれらを定義するクラスが読み込まれるときに共有プールに追加されます1。これにより、文字列リテラルのすべての「コピー」が実際には同じオブジェクトであることが保証されます...リテラルが複数のクラスに表示される場合でも. それが理由s3 == s4ですtrue

対照的に、newString の場合は、別個の新しい String オブジェクトが作成されます。それが理由s1 == s2ですfalse。(これは の基本的なプロパティですnew。正常に完了した場合、新しいオブジェクトを作成して返すことが保証されています。)

ただし、どちらの場合も、文字列には同じ文字が含まれるため、equalsは を返しtrueます。


何が起こっているのかを理解することは重要ですが、本当の教訓は、Java 文字列を比較する正しいequals方法は を使用し、 を使用しないこと==です。

を使用して String オブジェクトの等価性をテストできるようにしたい場合は==、 メソッドを使用してそれらを「インターン」できますString.intern。ただし、これを一貫して行う必要があります...そして、インターンはさまざまな点で費用のかかるプロセスです...したがって、一般的には良い考えではありません.


1 - 実際には、それよりも少し複雑です。これらのオブジェクトは、クラスのロードとリテラルの最初の使用の間のある時点でプールに追加されます。正確なタイミングは指定されておらず、JVM の実装に依存します。ただし、アプリケーション コードがStringリテラルに対応するオブジェクト参照を確認する前に、一度だけ発生することが保証されています。

于 2013-04-13T09:19:59.783 に答える
3

s1プールされたインスタンスの一部に属さない新しい String オブジェクトです。s3プールから取得される文字列のインスタンスです。Java String プールを検索します。の関連するintern()メソッドを見てくださいString

この概念は Java に固有のものではありません。文字列インターンは他の言語でサポートされています。これに関連して、頻繁に使用されるオブジェクトのプーリングはフライウェイトパターンに従い、文字列に限定されません。をご覧くださいInteger.valueOf()。整数にも独自の定数プールがあります。

于 2013-04-13T09:19:16.187 に答える
2

JVM には自動最適化機能があります。明確に新しいオブジェクトを作成し、同じ値を持つString別のオブジェクトが既に存在する場合を除き、 は自動的に新しいオブジェクトは不要であると見なし、既に存在する同等のオブジェクトへのポインタを割り当てます。StringJVMString

基本的に、2 番目のオプションを使用すると、次のようになります。

ステップ1

最初のオブジェクトは問題なく作成されます。

ステップ2

2 番目のオブジェクトが作成される前に、String プールの値がチェックされます。その値が現在存在する場合、新しいオブジェクトを作成する必要はありません。Stringオブジェクトへの参照を返すだけです。

ステップ 3

新しいオブジェクトが割り当てられる代わりに、ステップ 1 で作成されたオブジェクトへの参照が与えられます。これはメモリを節約するためです。

于 2013-04-13T09:15:00.610 に答える
0

これは、new演算子が String の新しいインスタンスの作成を強制するために発生しますが、2 番目のケースでStringは、不変クラスと同様に、JVM はメモリを節約するために両方の変数に同じ String インスタンスを提供します。そのようなオブジェクトの 1 つが変更されて 2 番目のオブジェクトも変更される可能性はないため (不変、覚えていますか?)、これで問題ありません。

于 2013-04-13T09:20:24.943 に答える