-1

以下代码将创建多少个对象?

String temp = "a" + "b" + "c"

我的理解:a、b 和 c 是字符串文字,将存储在字符串池中(因此不会创建新对象)。然后在使用“+”运算符附加时,它在内部使用 StringBuffer,因此将创建 1 个对象,该对象将保存“abc”(StringBuffer)。它将在一个新的 String 对象中返回(其值为“abc”)。

-> 因此,据我所知,在此操作期间将创建总共 2 个对象。(一个 String 和一个 StringBuffer)。

-> 字符串“abc”也不会出现在字符串池中。

我错了吗?

4

1 回答 1

4

从此测试代码:

public class Test {
    public static void main(final String[] args) {
        String temp = "a" + "b" + "c";
    }
}

你得到这个字节码:

public static void main(java.lang.String[]);
  Code:
     0: ldc           #2                  // String abc
     2: astore_1      
     3: return 

使用这个常量池:

Constant pool:
   #1 = Methodref          #4.#13         //  java/lang/Object."<init>":()V
   #2 = String             #14            //  abc
   #3 = Class              #15            //  Test
   #4 = Class              #16            //  java/lang/Object
   #5 = Utf8               <init>
   #6 = Utf8               ()V
   #7 = Utf8               Code
   #8 = Utf8               LineNumberTable
   #9 = Utf8               main
  #10 = Utf8               ([Ljava/lang/String;)V
  #11 = Utf8               SourceFile
  #12 = Utf8               Test.java
  #13 = NameAndType        #5:#6          //  "<init>":()V
  #14 = Utf8               abc
  #15 = Utf8               Test
  #16 = Utf8               java/lang/Object

所以你错了。一个String已创建——"abc"并在运行时放入String池中。

此处的编译器执行了常量折叠并将编译时常量表达式简化"a" + "b" + "c""abc". 如果使用标志进行编译,则可以看到这一点,该-XD-printflat标志显示了编译器编译为字节码的实际源代码:

public static void main(final String[] args) {
    String temp = "abc";
}

如果您想查看实际的String串联,则必须使用不是编译时常量的操作数,例如变量:

public static void main(final String[] args) {
    String a = "a";
    String b = "b";
    String c = "c";
    String temp = a + b + c;
}

编译为:

public static void main(java.lang.String[]);
  Code:
     0: ldc           #2                  // String a
     2: astore_1      
     3: ldc           #3                  // String b
     5: astore_2      
     6: ldc           #4                  // String c
     8: astore_3      
     9: new           #5                  // class java/lang/StringBuilder
    12: dup           
    13: invokespecial #6                  // Method java/lang/StringBuilder."<init>":()V
    16: aload_1       
    17: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    20: aload_2       
    21: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    24: aload_3       
    25: invokevirtual #7                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
    28: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
    31: astore        4
  33: return        
于 2014-06-01T15:25:18.667 回答