字符串概念的困惑

Jai*_*Das 0 java

class StringTest1
{
public static final void main(String... a)
{
    String str1="JAVA";
    String str2="WORLD";

    String str3=str1+str2;
}
}
Run Code Online (Sandbox Code Playgroud)

在此过程中将创建多少个对象?我想会创建3个对象.

class StringTest2
{
public static final void main(String... a)
{

    String strTest="JAVA"+"WORLD";
}
}
Run Code Online (Sandbox Code Playgroud)

在此过程中将创建多少个对象?可以访问多少个对象?有人告诉我"JAVA"+"WORLD"是一个表达式,它不会存储在字符串池中.

Viv*_*ath 5

在第一个示例中,您将最终得到三个String对象.您实际上可以在字节码中看到这一点.

假设您有以下代码:

public class StrTest {
    public static void main(String[] args) {
        String str1 = "JAVA";
        String str2 = "WORLD";

        String str3 = str1 + str2;

        String strTest = "JAVA" + "WORLD";
    }
}
Run Code Online (Sandbox Code Playgroud)

生成的字节码是:

public class StrTest {
  public StrTest();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String JAVA
       2: astore_1      
       3: ldc           #3                  // String WORLD
       5: astore_2      
       6: new           #4                  // class java/lang/StringBuilder
       9: dup           
      10: invokespecial #5                  // Method java/lang/StringBuilder."<init>":()V
      13: aload_1       
      14: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      17: aload_2       
      18: invokevirtual #6                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      21: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      24: astore_3      
      25: ldc           #8                  // String JAVAWORLD
      27: astore        4
      29: return        
}
Run Code Online (Sandbox Code Playgroud)

你可以看到,Java编译器设立了两个String实例为"JAVA""WORLD"在字符串池中.为了将这两者附加在一起,它创建了一个StringBuilder实例并附加了值.之后,它调用toString()该实例,在其中创建一个新String实例"JAVAWORLD".

在第二种情况下,您最终只得到一个String实例,因为Java编译器足够聪明,可以看到您基本上拥有的是一个常量,因此它通过计算表达式并在字符串中创建一个 String实例来执行一些编译时优化包含的池"JAVAWORLD".然后分配对该实例的引用strTest.

关于字符串"JAVA","WORLD""JAVAWORLD",这些基本上是实习字符串.由于字符串在Java中是不可变的,因此您只需要对一个唯一实例的一个引用,该实例可以在代码中的多个位置重用.这基本上是一种节省内存的方法.

总结一下:

  • 情况1:三个String实例:池中有两个实例,一个在追加后新构造的StringBuilder实例(还创建了一个实例来附加两个字符串,总共产生4个对象).
  • 案例2:池中的一个实例.