4

文字列がJavaでインターンされているかどうかを確認する方法についてこの回答を読みましたが、次の結果がわかりません。

String x = args[0]; // args[0] = "abc";
String a = "a";
String y = a + "bc";
System.out.println(y.intern() == y); // true

しかし、文字列リテラルを宣言すると、次のようになります。

String x = "abc";
String a = "a";
String y = a + "bc";
System.out.println(y.intern() == y); // false

その上、文字列リテラルがなければ、はargs[0]直接インターンされているようです。

// String x = "abc";
String y = args[0];
System.out.println(y.intern() == y); // true (???)
// false if the first line is uncommented

コマンドライン引数を使用した場合でも、リテラルy.intern() == yかどうかによって変化するのはなぜですか?x

リテラル文字列がコンパイル時にインターンされることは知っていますが、前の例で影響する理由がわかりません。文字列プールの動作Javaの文字列プールとJava文字列プールに関する質問など、文字列のインターンに関するいくつかの質問も読みました-プールはいつ変更されますか?。しかし、それらのどれもこの振る舞いに可能な説明を与えていません。

編集:

String x = "abc";3番目の例では、が宣言されていても結果は変わらないと間違って書きましたが、変わります。

4

2 に答える 2

6

これは、文字列が以前に強制収容されていなかった場合にy.intern()返還されるためです。y文字列がすでに存在する場合、呼び出しは、とは異なる可能性が最も高い既存のインスタンスを返しますy

ただし、これはすべて実装に大きく依存するため、JVMとコンパイラのバージョンによって異なる場合があります。

于 2013-02-23T18:28:27.837 に答える
0

実装の詳細は異なる場合があります。しかし、これはまさに私が期待する動作です。最初のケースは、コマンドライン引数がデフォルトでインターンされていないことを意味します。したがって、インターン後にy.intern()への参照を返します。y

2番目のケースは、VMがリテラルを自動的にインターンするため、y.intern()への参照を返します。xこれは、とは異なりyます。

また、デフォルトでは何もインターンされていないため、最後のケースが再び発生します。したがって、を呼び出すと、へintern()の参照が返されますy 。Stringをより積極的にインターンすることは合法だと思いますが、私が理解しているように、これは仕様に必要な最小限の動作です。

于 2013-02-23T18:52:07.193 に答える