JLS示例3.10.5-1之间的区别.字符串文字和Oracle JDK?

tb-*_*tb- 5 java

规格

例3.10.5-1.Java语言规范8的字符串文字告诉我们:


该程序由编译单元组成(第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"; }
Run Code Online (Sandbox Code Playgroud)

和编译单位:

package other;
public class Other { public static String hello = "Hello"; }
Run Code Online (Sandbox Code Playgroud)

产生输出:

true true true true false true
Run Code Online (Sandbox Code Playgroud)

现实

但编译并运行oracle jdk 1.8.0_65(win)输出

true true true true true true
Run Code Online (Sandbox Code Playgroud)

问题1

为什么会有所不同?(我有一个猜测,并会发布答案)

问题2

这是规范或编译器或解释器中的错误吗?

如果有的话,在哪里举报?


版本

"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
Run Code Online (Sandbox Code Playgroud)

tb-*_*tb- 4

回答问题1

javac编译器在编译时进行优化。

编译器将其识别为常量表达式:

String lo = "lo";
Run Code Online (Sandbox Code Playgroud)

并得出结论,这也必须是一个常量表达式:

"Hel" + lo
Run Code Online (Sandbox Code Playgroud)

因此,假设整个术语被保留为字符串值常量表达式,我们将保留字符串与相等的保留字符串进行比较。因此,我们比较相同的参考文献并得到true完整的检查,可以将其预先评估为真实。

证据

  1. 字节码 ( javap -c) 表明我们有一些预先计算。1.、4. 和 5. 打印中的表达式仅替换为"true".
  2. 以下代码解除优化:

来源

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());
  }
}
Run Code Online (Sandbox Code Playgroud)

输出:

true true true true false true
Run Code Online (Sandbox Code Playgroud)

  • 尽管“JIT”是最聪明的,但他的兄弟编译器也不是完全愚蠢的。 (2认同)