1
class A {
    String s = "abc";
}

class B {
    String s = "abc";

     static public void main(String[]args ) {
            A a = new A();
            B b = new B();
            System.out.println("a.s==b.s : " + (a.s==b.s));
     }
}

出力:

a.s==b.s : true

リテラルがクラスファイルの「定数プール」部分に書き込まれる場合、2つのクラスの2つのリテラル(同じ内容)が同じインターン文字列を使用するのはなぜですか?コンパイラはそれらをどのようにリンクしますか?

4

3 に答える 3

4

これは、Java言語仕様のセクション3.10.5に記載されているとおりです。

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

次に、説明に含まれる例があります。

異なるパッケージの異なるクラス内のリテラル文字列は、同様に同じStringオブジェクトへの参照を表します。

String.intern()このように文書化されています:

文字列オブジェクトの正規表現を返します。

最初は空の文字列のプールは、Stringクラスによってプライベートに維持されます。

インターンメソッドが呼び出されたときに、equals(Object)メソッドによって決定されたこのStringオブジェクトに等しい文字列がプールにすでに含まれている場合、プールからの文字列が返されます。それ以外の場合、このStringオブジェクトはプールに追加され、このStringオブジェクトへの参照が返されます。

したがって、任意の2つの文字列sおよびtについて、s.equals(t)が真である場合に限り、s.intern()== t.intern()が真になります。

すべてのリテラル文字列と文字列値の定数式がインターンされます。文字列リテラルは、Java™言語仕様のセクション3.10.5で定義されています。

これらはすべて、例で見た動作を示しています。

于 2012-05-20T13:08:07.273 に答える
1

すべてのインターンされたオブジェクトが入る文字列プールがあります。Stringそれは事実上HashMap<String>です。メソッドが;String.intern()を返すことに注意してください。String実装は本質的に

if (stringPool.contains(this))
    return stringPool.get(this);
else {
    stringPool.put(this, this);
    return this;
}

クラスのロード中にStringオブジェクトが作成されると、それは呼び出しの結果に置き換えられintern()ます。これは、すべてのクラス間でインスタンスのように共有する結果になります。

于 2012-05-20T13:03:51.513 に答える
1

すべてのインターンされた文字列を含むのを想像してみてくださいstatic final Set<String>String.classロードされた同じクラスを共有するすべてのクラスStringには、同じインターン文字列が表示されます。はルートクラスローダーの1つによってロードされるためString、単一のJVMインスタンス内のすべてのものによって共有されます。

于 2012-05-20T13:10:16.317 に答える