JLS例子3.10.5-1字符串字面值和Oracle JDK之间的区别是什么?

6

规范

Java语言规范第8版中的例子3.10.5-1.字符串字面量告诉我们:


由编译单元(§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(Windows)进行编译和运行会产生以下输出:

true true true true true true

问题 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
1个回答

4

问题1的答案

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

编译器把这个识别为常数表达式:

String lo = "lo";

并得出结论这也必须是一个常量表达式:
"Hel" + lo

因此,假设整个术语作为字符串类型的常量表达式已被存储 ,我们将一个存储的字符串与相同的存储字符串进行比较。因此,我们比较相同引用并得到true结果,完整的检查可以预先评估为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());
  }
}

输出:

true true true true false true

2
尽管JIT是聪明的,但他的兄弟编译器也并非完全愚蠢。 - Kayaman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接