Example 3.10.5-1. String Literals告诉我们:
由编译单元组成的程序(第7.3节):
package testPackage;
class Test {
public static void main(String[] args) {
String hello = "Hello", lo = "lo";
System.out.print((hello == "Hello") + " ");
System.out.print((Other.hello == hello) + " ");
System.out.print((other.Other.hello == hello) + " ");
System.out.print((hello == ("Hel"+"lo")) + " ");
System.out.print((hello == ("Hel"+lo)) + " ");
System.out.println(hello == ("Hel"+lo).intern());
}
}
class Other { static String hello = "Hello"; }
和编译单元:
package other;
public class Other { public static String hello = "Hello"; }
产生输出:
true true true true false true
但编译并运行oracle jdk 1.8.0_65(win)输出
true true true true true true
为什么会有所不同? (我有猜测并会发布答案)
这是规范或编译器或解释器中的错误吗?
如果有的话,在哪里举报?
"c:\Program Files\Java\jdk1.8.0_65\bin\java.exe" -version
java version "1.8.0_65"
Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)
"c:\Program Files\Java\jdk1.8.0_65\bin\javac.exe" -version
javac 1.8.0_65
答案 0 :(得分:3)
javac编译器在编译期间进行优化。
编译器将此识别为常量表达式:
String lo = "lo";
并得出结论,这也必须是一个常量表达式:
"Hel" + lo
因此假设整个术语是interned作为字符串值常量表达式,我们将一个实习字符串与一个相等的实习字符串进行比较。因此,我们比较相同的引用并获得true
,并且可以将完整检查预先评估为真。
javap -c
)向我们显示我们有一些预先计算。 1.,4和5. print中的表达式仅替换为"true"
。来源
public class StringTest {
public static void main(final String[] args) {
final String hello = "Hello", lo = "lo";
String myLo = "";
if (Math.random() < 10) {
myLo = "lo";
}
System.out.print((hello == "Hello") + " ");
System.out.print((Other.hello == hello) + " ");
// System.out.print((other.Other.hello == hello) + " "); // same package
System.out.print((hello == ("Hel" + "lo")) + " ");
System.out.print((hello == ("Hel" + lo)) + " ");
System.out.print((hello == ("Hel" + myLo)) + " ");
System.out.println(hello == ("Hel" + lo).intern());
}
}
输出:
true true true true false true