検討してください:
_String s1 = new StringBuilder("Cattie").append(" & Doggie").toString();
System.out.println(s1.intern() == s1); // true why?
System.out.println(s1 == "Cattie & Doggie"); // true another why?
String s2 = new StringBuilder("ja").append("va").toString();
System.out.println(s2.intern() == s2); // false
String s3 = new String("Cattie & Doggie");
System.out.println(s3.intern() == s3); // false
System.out.println(s3 == "Cattie & Doggie"); // false
_
String.intern()
の戻り値によって結果が異なる理由を混乱させました:
Internメソッドが呼び出されたときに、equals(Object)メソッドによって決定されたこのStringオブジェクトに等しい文字列がプールにすでに含まれている場合、プールからの文字列が返されます。それ以外の場合、このStringオブジェクトはプールに追加され、このStringオブジェクトへの参照が返されます。
特にこれらの2つのテストの後:
_assertFalse("new String() should create a new instance", new String("jav") == "jav");
assertFalse("new StringBuilder() should create a new instance",
new StringBuilder("jav").toString() == "jav");
_
私はかつて、何よりも先にインターンされた_special strings
_について話している投稿を読んだことがありましたが、今は本当にぼやけています。
_pre-interned
_の文字列がある場合、それらのリストのようなものを取得する方法はありますか?私は彼らが何ができるのか知りたいだけです。
@Eranと@Slawの協力のおかげで、出力で何が起こったのかを最終的に説明できます
_true
true
false
false
false
_
"Cattie & Doggie"
_はプールに存在しないため、s1.intern()は現在のオブジェクト参照をプールに入れてそれ自体を返すため、s1.intern() == s1
;"Cattie & Doggie"
_は既にプールにあるため、文字列リテラル_"Cattie & Doggie"
_は、実際には_s1
_であるプール内の参照を使用するだけなので、再度true
;を使用します。new StringBuilder().toString()
は、_"Java"
_がすでにプールにあるときに新しいインスタンスを作成し、s2.intern()
を呼び出すとプール内の参照が返されるため、s2.intern() != s2
とfalse
;new String()
も新しいインスタンスを返しますが、s3.intern()
を実行しようとすると、実際に_s1
_であるため、プールに以前に格納された参照が返されますs3.intern() != s3
false
;"Cattie & Doggie"
_は、プールに既に格納されている参照(実際には_s1
_)を返すため、_s3 != "Cattie & Doggie"
_とすると、再びfalse
になります。すべてのinterned
文字列を取得するためのトリックを提供してくれた@Sunnyに感謝します。
文字列リテラル(「文字列」のようにハードコードされているもの)は、コンパイラーによってすでにインターンされています。ただし、プログラムで取得される文字列はそうではなく、.intern()
メソッドを使用する場合にのみインターンされます。
通常、文字列を手動でインターンすることはありませんが、繰り返し文字列を大量にメモリに格納することがわかっている場合を除き、この方法で多くのメモリを節約できます。
これはここで説明されています: Java String interning? とは