Java字符串连接和对象

时间:2014-06-01 15:14:16

标签: java string concatenation string-pool

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

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

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

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

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

我错了吗?

1 个答案:

答案 0 :(得分: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