如果使用String实现String连接是使用StringBuilder实现的,那么为什么在连接期间会创建额外的对象?

时间:2010-11-12 21:46:35

标签: java string stringbuilder

如果以下代码:

String s = "a" + 1 + "b";// 1.

使用等效于

的StringBuilder实现
String s = new StringBuilder().append("a").append(1).append("b");

然后会在1中创建额外的对象“a”和“b”,为什么?

3 个答案:

答案 0 :(得分:5)

您的示例实际上不会使用StringBuilder,因为没有元素是变量。因为“a”,1和“b”都是文字,编译器会为你制作一个String!但是,如果您在String并置中包含变量,那么它将使用StringBuilder,并且对于连接元素需要单独的String

对于您的示例,编译器将创建单个字符串文字:

const #2 = String       #21;    //  a1b

public void foo();
  Code:
   Stack=1, Locals=2, Args_size=1
   0:   ldc     #2; //String a1b
   2:   astore_1
   3:   return
  LineNumberTable: 
   line 7: 0
   line 8: 3

让我们说我们写了

public void bar(String c)
{
    String s = "a" + c + "b";// 1.
}

现在编译器需要创建一个StringBuilder,它将使用带有StringBuilder的a和b常量ASCII文字。

const #20 = Asciz       a;
const #22 = Asciz       b;

public void bar(java.lang.String);
  Code:
   Stack=2, Locals=3, Args_size=2
   0:   new     #2; //class java/lang/StringBuilder
   3:   dup
   4:   invokespecial   #3; //Method java/lang/StringBuilder."<init>":()V
   7:   ldc     #4; //String a
   9:   invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava    /lang/String;)Ljava/lang/StringBuilder;
   12:  aload_1
   13:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   16:  ldc     #6; //String b
   18:  invokevirtual   #5; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   21:  invokevirtual   #7; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   24:  astore_2
   25:  return
  LineNumberTable: 
   line 7: 0
   line 8: 25

答案 1 :(得分:2)

我假设您想知道为什么在字符串上使用StringBuilder而不是+运算符会更有效率。在您的示例中,差异可以忽略不计,但您必须考虑更大的问题,通常是由循环引起的。

以下面的代码为例:

String s = "";
for(int i = 0; i < 100000; i++) {
   s = s + "something";
}

无论如何,如果您使用StringBuilder来优化此+操作,则可以创建String对象以存储在s中。因此,每个循环迭代将创建一个新的String对象,为您提供大量新创建的对象。

相反,如果在循环中使用StringBuildersb.append("something"),则不需要StringBuilder为每个循环迭代创建String对象。它可以自由地等待创建一个,直到循环后需要它。

答案 2 :(得分:1)

我认为你把它混合了一点......

对于+ - 案例,在评估"a1"时(在"a" + 1"a1"连接之前),会创建一个额外的"b" - 对象。使用append方法时,可以避免创建额外的对象。多数民众赞成。

在编译期间已经创建了"a""b"。 (那些常量文字将从一开始就存在于sting池中。)但是正如您可能知道的那样,这些常量也将在append情况下创建。