When I compile this snippet.
public class InternTest {
public static void main(String...strings ){
final String str1="str";
final String str2="ing";
String str= str1+str2;
}
}
Which produces the following byte code
public static void main(java.lang.String...);
flags: ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
Code:
stack=1, locals=4, args_size=1
0: ldc #16 // String str
2: astore_1
3: ldc #18 // String ing
5: astore_2
6: ldc #20 // String string
8: astore_3
9: return
so string literal "string" is already there in the constant pool which gets pushed 6: ldc #20 // String string
on stack at this line.
Quoting JSL
From JLS §4.12.4 - final Variables:
A variable of primitive type or type String, that is final and initialized with a compile-time constant expression (§15.28), is called a constant variable.
Also from JLS §15.28 - ConstantExpression:
Compile-time constant expressions of type String are always "interned" so as to share unique instances, using the method String#intern().
So i know str1 and str2 will be interned the moment it has been created."str" and "ing" will share the same memory at line String str= str1+str2;
But how str1+str2 directly produces "string" in the constant string pool. Without invoking any String Builder class like it does when i don't write final
. ? To see if it has got anything to do with intern things
I wrote this snippet
public class IntermTest {
public static void main(String...strings ){
String str1=("str").intern();
String str2=("ing").intern();
String str= str1+str2;
}
}
But when i generated the byte code i got this
public static void main(java.lang.String...);
flags: ACC_PUBLIC, ACC_STATIC, ACC_VARARGS
Code:
stack=3, locals=4, args_size=1
0: ldc #16 // String str
2: invokevirtual #18 // Method java/lang/String.intern:
()Ljava/lang/String;
5: astore_1
6: ldc #24 // String ing
8: invokevirtual #18 // Method java/lang/String.intern:
()Ljava/lang/String;
11: astore_2
12: new #26 // class java/lang/StringBuilder
15: dup
16: aload_1
17: invokestatic #28 // Method java/lang/String.valueOf
:(Ljava/lang/Object;)Ljava/lang/String;
20: invokespecial #32 // Method java/lang/StringBuilder.
"<init>":(Ljava/lang/String;)V
23: aload_2
24: invokevirtual #35 // Method java/lang/StringBuilder.
append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
27: invokevirtual #39 // Method java/lang/StringBuilder.
toString:()Ljava/lang/String;
30: astore_3
31: return
Indeed it also uses stringBuilder
for concatenation. So it has do something with final. Is there something special about final
Strings that I'm definitely not aware of ?
http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28 says that
http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.28 also says:
Since those two variables are constant expressions, the compiler does the concatenation:
is compiled the same way as
which is compiled the same way as