Strange String pool behavior
"555" + ""
is a compile-time constant, whereas
giveLiteralString() + ""
isn't. Therefore the former compiles into just the string constant "555" and the latter compiles into the actual method invocation and concatenation, resulting in a fresh String instance.
Also see JLS §3.10.5 (String Literals):
Strings computed by concatenation at run time are newly created and therefore distinct.
After decompiling this line
System.out.println("555" == "555" + "");
I got this bytecode
LINENUMBER 8 L0
GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
ICONST_1
INVOKEVIRTUAL java/io/PrintStream.println(Z)V
...
which is equivalent to
System.out.println(true);
that means expression "555" == "555" + ""
compiles to boolean true
.
For giveLiteralString() == giveLiteralString() + ""
javac built this bytecode
LINENUMBER 8 L0
INVOKESTATIC Test1.giveLiteralString()Ljava/lang/String;
NEW java/lang/StringBuilder
DUP
INVOKESTATIC Test1.giveLiteralString()Ljava/lang/String;
INVOKESTATIC java/lang/String.valueOf(Ljava/lang/Object;)Ljava/lang/String;
INVOKESPECIAL java/lang/StringBuilder.<init>(Ljava/lang/String;)V
INVOKEVIRTUAL java/lang/StringBuilder.toString()Ljava/lang/String;
IF_ACMPNE L1
...
which is equivalent to
if (giveLiteralString() == new StringBuilder(giveLiteralString()).append("").toString()) {
...
which will always produce false since here we're comparing 2 disctinct objects.
In the second case the compiler COULD have recognized that + ""
is a no-op of sorts, since ""
is a compile-time value known to be zero length. But the compiler is still required to check the result from giveLiteralString
for null (since the null check would occur as a result of the +
operation in the non-optimized case), so it's simplest to just not attempt the optimization.
As a result, the compiler generates code to perform the concatenation, and a new string is created.