假设优化器不聪明,创建了两个对象。(足够聪明的优化器可以将其优化为无条件的true
,在这种情况下不会创建任何对象。)
tl;dr 版本:您对 3 的回答几乎是正确的,只是进入字符串池的字符串不是作为该语句的一部分生成的;它已经创建好了。
首先,让我们把"ABC"
字面意思去掉。它在运行时表示为一个String
对象,但它存在于 pergen 中并且在 JVM 的整个生命周期中被创建一次。如果这是第一个使用该字符串文字的类,则它是在类加载时创建的(请参阅JLS 12.5,其中指出 String 是在加载类时创建的,除非它以前存在)。
因此,第一个new String("ABC")
创建 one String
,它只是将引用(但不创建新对象)复制"ABC"
到 chars 数组并从表示文字的 String 散列(同样,它不是作为该行的一部分创建的)。然后该.intern()
方法查看是否已在 permgen 中存在相等的字符串。它是(它只是表示以文字开头的字符串),所以这就是该函数返回的内容。所以,new String("ABC").intern() == "ABC"
。请参阅JLS 3.10.5,特别是:
此外,字符串字面量总是引用 String 类的同一个实例。这是因为字符串字面量 - 或者更一般地说,作为常量表达式值的字符串(第 15.28 节) - 是“内部的”,以便使用 String.intern 方法共享唯一实例。
同样的事情发生在第二次出现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.