如果以下代码:
String s = "a" + 1 + "b";// 1.
使用等效于
的StringBuilder实现String s = new StringBuilder().append("a").append(1).append("b");
然后会在1中创建额外的对象“a”和“b”,为什么?
答案 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
对象,为您提供大量新创建的对象。
相反,如果在循环中使用StringBuilder
和sb.append("something")
,则不需要StringBuilder
为每个循环迭代创建String
对象。它可以自由地等待创建一个,直到循环后需要它。
答案 2 :(得分:1)
我认为你把它混合了一点......
对于+
- 案例,在评估"a1"
时(在"a" + 1
与"a1"
连接之前),会创建一个额外的"b"
- 对象。使用append
方法时,可以避免创建额外的对象。多数民众赞成。
在编译期间已经创建了"a"
和"b"
。 (那些常量文字将从一开始就存在于sting池中。)但是正如您可能知道的那样,这些常量也将在append
情况下创建。