Your first two lines are almost correct. Technically, those two lines of code don't create any objects on their own -- the string literals are actually processed at compile time and placed into the constants pool in the bytecode file, which means the actual String
objects are created when the class is first loaded, before any of the code you wrote runs. Thus, if you were to decompile the first two lines of your code you'd get this:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: aload_0
5: ldc #2 // String java
7: putfield #3 // Field s1:Ljava/lang/String;
10: aload_0
11: ldc #2 // String java
13: putfield #4 // Field ss:Ljava/lang/String;
16: return
As you can see, no String
objects are created by either line. The bytecode merely assigns preexisting String
values from the constant pool (ldc
means load constant
) to those variables
The next two lines are a bit different. It's probably easier to figure out what's going on if you split the chained calls into their component parts:
String s2 = new String("Android");
s2 = s2.intern();
String s3 = new String("java");
s3 = s3.intern();
This gets compiled to this bytecode:
0: new #2 // class java/lang/String
3: dup
4: ldc #3 // String Android
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: astore_1
15: new #2 // class java/lang/String
18: dup
19: ldc #6 // String java
21: invokespecial #4 // Method java/lang/String."<init>":(Ljava/lang/String;)V
24: astore_2
25: aload_2
26: invokevirtual #5 // Method java/lang/String.intern:()Ljava/lang/String;
29: astore_2
30: return
So you can see that the new
keyword triggers the construction of a new String
object. Then the string "Android"
is loaded from the constant pool and used to create the string. This is then stored into a variable. Immediately after, the variable is dereferenced, intern()
invoked, and the result stored back into the variable. The only difference between this code and your code would be the extra store/load in between String
construction and interning.
So for each of s2
and s3
, only one String
object is created -- hence, you only see two methods with <init>
total. All intern()
does is check to see whether that that string already exists in the string pool, and if it does, returns that one reference.