Example 3.10.5-1. String Literals of the Java Language Specification 8 tells us this:
The program consisting of the 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 the compilation unit:
package other;
public class Other { public static String hello = "Hello"; }
produces the output:
true true true true false true
But the compilation and run with oracle jdk 1.8.0_65 (win) outputs
true true true true true true
Why is this different? (I have a guess and will post the answer)
Is this a bug in the specification or the compiler or the interpreter?
If any of this, where to report?
"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
The javac compiler does optimization during compile time.
The compiler recognize this as a constant expression:
String lo = "lo";
and concludes that this must be a constant expression too:
"Hel" + lo
and therefore assuming the whole term is interned as a string-valued constant expression, we compare an interned string against an equal interned string. Therefore we compare the same references and get true
and the complete check can be pre-evaluated as true.
javap -c
) shows us that we have some precalculations. The expressions from the 1., 4. and 5. print are just replaced with a "true"
.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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With