オプティマイザーに賢さがないと仮定すると、2 つのオブジェクトが作成されます。(十分に賢いオプティマイザは、これを無条件true
に最適化できます。その場合、オブジェクトは作成されません。)
tl;dr version: String プールに入る文字列がこのステートメントの一部として生成されないことを除いて、3 の答えでほとんど正解でした。すでに作成されています。
"ABC"
まず、リテラルを邪魔にならないようにしましょう。ランタイムではString
オブジェクトとして表されますが、それは pergen に存在し、JVM の存続期間中に一度だけ作成されます。これがその文字列リテラルを使用する最初のクラスである場合、それはクラスのロード時に作成されました ( JLS 12.5を参照してください。以前に存在していた場合を除き、クラスがロードされたときに String が作成されたと記載されています)。
そのため、最初にnew String("ABC")
を作成します。これは参照を chars 配列String
に単純にコピーし"ABC"
(ただし、新しいオブジェクトは作成しません)、リテラルを表す String からハッシュします(これも、この行の一部として作成されません)。この.intern()
メソッドは、等しい文字列がすでに permgen にあるかどうかを調べます。それは (最初にリテラルを表す文字列に過ぎない) なので、それがその関数が返すものです。だから、new String("ABC").intern() == "ABC"
。JLS 3.10.5を参照してください。特に:
さらに、文字列リテラルは常に String クラスの同じインスタンスを参照します。これは、文字列リテラル (より一般的には、定数式の値である文字列 (§15.28)) が、メソッド String.intern を使用して一意のインスタンスを共有するために「インターン」されているためです。
の 2 回目の発生でもまったく同じことが起こりnew String("ABC").intern()
ます。また、どちらのメソッドもリテラルintern()
と同じオブジェクトを返すため、同じ値を表します。"ABC"
少し分解します:
String a = new String("ABC"); // a != "ABC"
String aInterned = a.intern(); // aInterned == "ABC"
String b = new String("ABC"); // b != "ABC"
String bInterned = b.intern(); // bInterned == "ABC"
System.out.println(new String("ABC").intern()==new String("ABC").intern());
// ... is equivalent to...
System.out.println(aInterned == bInterned); // ...which is equivalent to...
System.out.println("ABC" == "ABC"); // ...which is always true.