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.