What is the difference between an addition of String Literal and String Object?
For example
String s1 ="hello";
String s2 ="hello1";
String s3 ="hello" + "hello1";
String s4 ="hellohello1";
String s5 = s1 + s2;
System.out.println(s3 == s4); // returns true
System.out.println(s3 == s5); // return false
System.out.println(s4 == s5); // return false
Why do s3
/s4
not point to the same location as s5
?
Because
s1 + s2
is not a constant expression, sinces1
ands2
are notfinal
, therefore its result is not interned, i.e. another object is created to represent it, so reference comparison producesfalse
.JLS 3.10.5 String Literals:
JLS 15.28 Constant Expression:
JLS 4.12.4 defines
final
variables.If you declare
s1
ands2
asfinal
,s3 == s5
would betrue
.Because you're comparing references. To compare contents, use
s1.equals(s2)
.If your comparison of references is intentional, it is unclear why you're expecting the compiler/JVM to intern or not intern identical strings arising in different ways.
EDIT: I assume that you know that you are comparing references, not the contents of the strings. If no,
s3.equals(s5)
is what you are looking for (as already mentioned).s3
is optimized by the compiler to"hellohello1"
which is reused fors4
as well.I'm quite surprised that the compiler isn't smart enough to do the same for. This optimization is only allowed for constant expressions (see 15.28 of Java Language Specification). In other words, any assignment to a non-final variable denies the possibility of later optimization.s5
though. Which JDK version are you using?Here's the output of
javap -c -l
of a simple class that wraps your code into a main method (not that anybody asked for it, but I'm curious myself). So let's see what's going on:I'm not to experienced reading byte code, but I'll give it a go :)
ldc #16
followed byastore_1
means "load constant #16 and store it in slot 1". As you can see, this is done 4 times at the beginning for slots 1 - 4 which translates to s1, s2, s3 and s4 (see LocalVariableTable).aload_1
) and slot 2 (aload_2
) involved before storing the result in slot 5 (astore 5
).Because the compiler optimizes concatenation of String literals.
In practice this should not matter (most of the time), as you usually want to compare Strings for equality using the equals method and not to check if the object references are the same.
Also note that you can intern s5 using e.g.:
This is rarely needed, though.