For the scenario 1:
String s = new String("1");
s.intern();
String s2 = "1";
System.out.println(s == s2);
with bytecode:
0: new #2 // class java/lang/String
3: dup
4: ldc #3 // String 1
6: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V
9: astore_1
10: aload_1
11: invokevirtual #5 // Method java/lang/String.intern:()Ljava/lang/String;
14: pop
15: ldc #3 // String 1
for String s = new String("1");
it will create a new String
object, it will have a new address with "1" that it is already in String Pool:
ldc #3 // String 1
and for s2
, as the bytecode:
15: ldc #3 // String 1
s2
is pointing to String Pool variable: "1"
, so s
and s2
have the different address and result is false
.
For the scenario 2:
String s3 = new String("1")+new String("1");
s3.intern();
String s4 = "11";
System.out.println(s3 == s4);
with bytecode:
0: new #2 // class java/lang/StringBuilder
3: dup
4: invokespecial #3 // Method java/lang/StringBuilder."<init>":()V
7: astore_1
8: aload_1
9: ldc #4 // String 1
11: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
14: ldc #4 // String 1
16: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #6 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_2
23: aload_2
24: invokevirtual #7 // Method java/lang/String.intern:()Ljava/lang/String;
27: astore_3
28: ldc #8 // String 11
As the bytecode, you can see new String("1")+new String("1");
is created by using StringBuilder
new #2 // class java/lang/StringBuilder
it's totally a new Object without String Pool variable.
and after s3.intern()
, this method will add current s3
to the Memory String Pool and 8: aload_1
.
and s4
is trying to load from
ldc #8 // String 11
so s3
and s4
address should equal and result is true.