5
public class A {

    static String s1 = "I am A";

    public static void main(String[] args) {
        String s2 = "I am A";
        System.out.println(s1 == s2);
    }
}

上記のプログラムは「true」を出力します。どちらも2つの異なる識別子/オブジェクトであり、出力はどのように「真」ですか?

私の理解では、JVMはオブジェクトごとに異なる参照を作成します。そうであれば、出力はどのように真になりますか?

4

5 に答える 5

20

JavaはStringリテラルプールを管理します。可能な場合は、これらのリテラルを再利用します。したがって、2つのオブジェクトは実際には同じStringオブジェクトであり、==trueを返します。

これはストリングインターンと呼ばれていると思います

于 2009-12-13T10:53:52.957 に答える
6

==変数がオブジェクトのまったく同じインスタンスを指していることを確認します。作成した2つの文字列リテラルは、メモリ内の同じ場所を指しているため、同じです。文字列リテラルは、同じ文字列リテラルがメモリ内の同じオブジェクトになるようにインターンされます。

あなたがするなら

String s = new String("foo");
String t = new String("foo");

次に、==はfalseを返し、s.equals(t)はtrueを返します。

于 2009-12-13T10:54:53.337 に答える
5

Java言語仕様には次のように書かれているためです。

文字列リテラル(または、より一般的には、定数式(§15.28)の値である文字列)は、メソッドString.internを使用して、一意のインスタンスを共有するように「インターン」されます。

于 2009-12-13T10:54:47.090 に答える
5

これは、コンパイラによって実行されるメモリの最適化が原因です...つまり、String定数 (つまり、同じリテラルStringによって作成された s ) は、不変であるため、同じオブジェクトを使用します。オペレーターは、2 つのオブジェクトが同じ実際のオブジェクトであることを確認するだけです。StringStringStrings==

Joshua Bloch と Neal Gafter による Java Puzzlers という本を手に取り、パズル 13 の「Animal Farm」を見ていただければ... 彼はこの問題について素晴らしいアドバイスをしてくれます。関連するテキストをいくつかコピーします。

「タイプのコンパイル時定数がインターンされていることに気付いているかもしれませんString[JLS 15.28]。つまり、同じ文字シーケンスを指定するタイプの2つの定数式はString、同一のオブジェクト参照によって表されます...あなたのコードは、あったとしてもめったにすべきではありません。 、文字列定数のインターンに依存しますインターンは、プログラマー向けのツールとしてではなく、仮想マシンのメモリフットプリントを削減するためにのみ設計されました... オブジェクト参照を比較するときは、必要でない限り、演算子よりもequalsメソッドを優先して使用する必要があります==値ではなくオブジェクトの同一性を比較します。」

それは私が言及した上記の参照からのものです...私の本の30〜31ページ。

于 2009-12-13T10:57:51.807 に答える
1

文字列の内容を比較しているのではありません。オブジェクトの参照を比較しているだけです。equalメソッド(Stringクラスのメンバー)を使用する必要があります。それか、compareToメソッド(これも同じStringクラスの下にあります)を使用して、戻り値がゼロかどうかを確認できます。

上記のテキストは、OPが舞台裏で行われている実際のプロセスを認識していないように見えたため、質問の元の状態をより強く示唆していることに注意してください。

内部化を示唆している他の人は正しかった。この質問に答えるために、私はJavaパズルの本に行くのに十分な時間がありませんでした。コンパイル時に同じ参照を設定することについて何か疑わしいことはありましたが、それへの参照を見つける方法もわかりませんでした。

于 2009-12-13T10:49:35.380 に答える