==
compares references, not sate. So if both references hold exact same object ==
returns true, if the hold different objects, even if their state is same it will return false
. To compare state of objects use equals
method.
Now difference between
String s2 = "roushan"+8;
String s3 = "roushan"+s1.length();
is that s1.length()
is not compile time constant (its value is not known at compilation time) while 8
is.
So when compiler knows value at compile time it can optimize our code, and concatenate strings once at compilation time, which means that
String s2 = "roushan"+8;
will be compiled as
String s2 = "roushan8";//there is no reason to repeat this concatenation every time at runtime
But for
String s3 = "roushan"+s1.length();
s1.length()
must be calculated at runtime, which means that this code will have to be compiled it into something like
String s3 = new StringBuilder("roushan").append(s1.length()).toString();
Now strings literals like "roushan8"
are by default interned (they end up in String literals pool, or are taken from them to avoid recreating same string twice). This means that
String s1 = "roushan8";
String s2 = "roushan8"; // <-- that is how "roushan"+8; will be compiled
will represent same interned "roushan8"
literal from string pool, which is confirmed by ==
.
But strings which ware created at runtime by using new String()
(and StringBuilder#toString
is internally creating new String()
) are not interned. This means they will not try to use literal representing same text, but will create separate new String instance, so even if that instance will contain same text, it will be treated as different object then the one from String pool, which is stored by s1
or s2
references.
You can confirm this by taking a look at bytecode of
String s1 = "roushan8";
String s2 = "roushan"+8;
String s3 = "roushan"+s1.length();
which is
0: ldc #19 // String roushan8
2: astore_1
3: ldc #19 // String roushan8
5: astore_2
6: new #21 // class java/lang/StringBuilder
9: dup
10: ldc #23 // String roushan
12: invokespecial #25 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
15: aload_1
16: invokevirtual #28 // Method java/lang/String.length:()I
19: invokevirtual #34 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
22: invokevirtual #38 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
25: astore_3
where we can see that
10 "roushan"
string is being loaded
12 and later used as argument in StringBuilder <initialization>
(constructor)
16 next value of s1.lenbth
is being calculated
19 and append to StringBuilder
22 now with StringBuilder#toString
method we create String representing concatenated text
23 and store it in s3
variable