我对String的实习方法没有很好的理解。
String s1="java"; // should create one object in String Constant pool
String ss="java"; // no object is created (java is already in String pool)..it refers to object in String constant pool
String s2= new String("Android").intern(); // should create 2 objects one in heap and second in String constant pool
String s3= new String("java").intern()// i guess only one object is created on heap and s3 will point to object in String constant pool (as 'java' already exist).so the object in heap is lost because there is no reference
请让我知道我的理解是否正确?
答案 0 :(得分:5)
前两行几乎正确。从技术上讲,这两行代码不会自己创建任何对象 - 字符串文字实际上是在编译时处理并放入字节码文件中的常量池中,这意味着在您编写的任何代码运行之前,首次加载类时会创建实际的String
个对象。因此,如果您要对代码的前两行进行反编译,那么您将获得:
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
如您所见,任何一行都不会创建String
个对象。字节码只是将常量池中的预先存在的String
值(ldc
表示load constant
)分配给那些变量
接下来的两行有点不同。如果将链式调用拆分为其组成部分,可能更容易弄清楚会发生什么:
String s2 = new String("Android");
s2 = s2.intern();
String s3 = new String("java");
s3 = s3.intern();
这会被编译为这个字节码:
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
因此,您可以看到new
关键字触发了新String
对象的构造。然后从常量池加载字符串"Android"
并用于创建字符串。然后将其存储到变量中。紧接着,变量被解除引用,intern()
被调用,结果存储回变量。此代码与您的代码之间的唯一区别是String
构造和实习之间的额外存储/加载。
因此,对于s2
和s3
中的每一个,只创建了一个String
对象 - 因此,您只能看到两个总共<init>
的方法。所有intern()
都检查字符串池中是否已存在该字符串,如果存在,则返回该引用。
答案 1 :(得分:0)
这一行
String s1="java";
或包含字符串文字的其他行不会创建String对象。它们是在加载包含字符串文字的类期间由JVM创建的,并放在String池中。
对于String.intern(),它不会创建一个新的String,它只是检查一个字符串是否已经在池中,如果它没有将它添加到池中