I have a simple question about strings in Java. The following segment of simple code just concatenates two strings and then compares them with ==.
If you take a look at this methods
public void noFinal() {
String str1 = "str";
String str2 = "ing";
String concat = str1 + str2;
System.out.println(concat == "string");
}
public void withFinal() {
final String str1 = "str";
final String str2 = "ing";
String concat = str1 + str2;
System.out.println(concat == "string");
}
and its decompiled with javap -c ClassWithTheseMethods
versions you will see
public void noFinal();
Code:
0: ldc #15 // String str
2: astore_1
3: ldc #17 // String ing
5: astore_2
6: new #19 // class java/lang/StringBuilder
9: dup
10: aload_1
11: invokestatic #21 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
14: invokespecial #27 // Method java/lang/StringBuilder."":(Ljava/lang/String;)V
17: aload_2
18: invokevirtual #30 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: invokevirtual #34 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
...
and
public void withFinal();
Code:
0: ldc #15 // String str
2: astore_1
3: ldc #17 // String ing
5: astore_2
6: ldc #44 // String string
8: astore_3
...
So if Strings are not final compiler will have to use StringBuilder to concatenate str1 and str2 so
String concat=str1+str2;
will be compiled to
String concat = new StringBuilder(str1).append(str2).toString();
which means that concat will be created at runtime so will not come from String pool.
Also if Strings are final then compiler can assume that they will never change so instead of using StringBuilder it can safely concatenate its values so
String concat = str1 + str2;
can be changed to
String concat = "str" + "ing";
and concatenated into
String concat = "string";
which means that concate will become sting literal which will be interned in string pool and then compared with same string literal from that pool in if statement.