The difference between the JLS example 3.10.5-1. String literals and Oracle JDK?

Specification

Example 3.10.5-1. String Literals The Java 8 language specifications tell us the following:


A program consisting of a compilation unit (ยง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"; } 

and compilation unit:

 package other; public class Other { public static String hello = "Hello"; } 

outputs the result:

 true true true true false true 

Reality

But compiling and starting with oracle jdk 1.8.0_65 (win) outputs

 true true true true true true 

Question 1

Why is it different? (I have an assumption and will post the answer)

Question 2

Is this a mistake in the specification or in the compiler or interpreter?

If any of this is where to report?


Version

 "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 
+5
source share
1 answer

Answer to question 1

The javac compiler performs optimization at compile time.

The compiler recognizes this as a constant expression:

 String lo = "lo"; 

and concludes that this should also be a constant expression:

 "Hel" + lo 

and therefore, assuming the whole term interned as a string meaningful expression, we compare the interned string to the same interned string. Therefore, we compare the same links and get true , and a full check can be preliminary evaluated as true.

Evidences

  • The bytecode ( javap -c ) shows us that we have some preliminary calculations. Expressions from images 1., 4., and 5. are simply replaced with "true" .
  • The following code disarms optimization:

A source

 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()); } } 

output:

 true true true true false true 
+3
source

Source: https://habr.com/ru/post/1234724/


All Articles