Java 使用String的intern方法时创建了多少个对象

Java 使用String的intern方法时创建了多少个对象,java,string,Java,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")

我对字符串的实习方法不是很了解

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
请让我知道我的理解是否正确

这条线

String  s1="java";
或其他包含字符串文字的行不创建字符串对象。它们由JVM在加载包含字符串文本的类时创建,并放置在字符串池中

至于String.intern(),它不会创建一个新字符串,它只是检查一个字符串是否已经在池中,如果它不在池中,则将其添加到池中。您的前两行几乎是正确的。从技术上讲,这两行代码本身并不创建任何对象——字符串文本实际上是在编译时处理的,并放入字节码文件的常量池中,这意味着实际的
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 
将其编译为以下字节码:

   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        
0:new#2//class java/lang/String
3:dup
4:ldc#3//String Android
6:invokespecial#4//方法java/lang/String.“:(Ljava/lang/String;)V
9:astore_1
10:aload_1
11:invokevirtual#5//方法java/lang/String.intern:()Ljava/lang/String;
14:astore_1
15:new#2//class java/lang/String
18:dup
19:ldc#6//字符串java
21:invokespecial#4//方法java/lang/String.“:(Ljava/lang/String;)V
24:astore_2
25:aload_2
26:invokevirtual#5//方法java/lang/String.intern:()Ljava/lang/String;
29:astore_2
30:返回
因此您可以看到,
new
关键字触发了一个新的
String
对象的构造。然后从常量池加载字符串“Android”,并用于创建字符串。然后将其存储到变量中。紧接着,变量被取消引用,
intern()
被调用,结果存储回变量中。此代码与您的代码之间的唯一区别是
String
构造和插入之间的额外存储/加载


因此,对于
s2
s3
中的每一个,只创建了一个
String
对象——因此,您只看到两个方法的
总数。
intern()
所做的只是检查字符串池中是否已经存在该字符串,如果存在,则返回该引用。

我认为这是对
字符串池的正确理解。因此,我所有的假设都是正确的?对于使用
新字符串的感觉是正确的,对象是在链接/类加载时创建的,而不是在编译时创建的。@chrylis肯定,我想你可以这样说。。。我更倾向于认为所有创建对象的信息都在编译时放在字节码的常量池中,但更合理的说法是,实际对象是在运行时的某个时候创建的。。。我会更正我的答案。
   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