Java StringBuilder中append的参数是新的字符串对象吗?它会被垃圾收集吗?
在下面的代码中,当它到达注释时,如果GC没有运行,将创建大约1000个对象(根据OCA手册),修改Java StringBuilder中append的参数是新的字符串对象吗?它会被垃圾收集吗?,java,string,garbage-collection,stringbuilder,Java,String,Garbage Collection,Stringbuilder,在下面的代码中,当它到达注释时,如果GC没有运行,将创建大约1000个对象(根据OCA手册),修改StringBuilder,并将其保留为一个对象,空字符串“将被合并并重新使用,这就是所解释的全部内容。参数s不是一个需要GCed的新字符串(“s”),并且i,它是否会首先转换为新字符串对象,然后与组合?创建另一个新字符串对象,使它们在该行成为两个字符串对象,符合GC条件的还有append的参数,每个循环中总共有3个String对象。那么,当代码到达注释行时,总共3000个对象 public cla
StringBuilder
,并将其保留为一个对象,空字符串“
将被合并并重新使用,这就是所解释的全部内容。参数s
不是一个需要GCed的新字符串(“s”)
,并且i
,它是否会首先转换为新字符串对象,然后与组合?
创建另一个新字符串对象,使它们在该行成为两个字符串对象,符合GC条件的还有append
的参数,每个循环中总共有3个String对象。那么,当代码到达注释行时,总共3000个对象
public class Mounds {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
String s = new String();
for (int i = 0; i < 1000; i++) {
s = " " + i;
sb.append(s);
}
// done with loop
}
}
公共类堆{
公共静态void main(字符串[]args){
StringBuilder sb=新的StringBuilder();
字符串s=新字符串();
对于(int i=0;i<1000;i++){
s=”“+i;
某人追加;
}
//完成循环
}
}
编译器可能意识到变量s
的作用域在循环中,因此它将赋值内联到append()
中以生成
sb.append(" " + i)
所以现在只有int的转换在每次迭代中创建一个新字符串 编译器可能意识到变量s
的作用域在循环内,因此它将赋值内联到append()
以生成
sb.append(" " + i)
所以现在只有int的转换在每次迭代中创建一个新字符串 如果我们编译这段代码并查看生成的字节码,我们可以准确地检查它
public static void main(java.lang.String[]) throws java.io.IOException;
Code:
0: new #19 // class java/lang/StringBuilder
3: dup
4: invokespecial #21 // Method java/lang/StringBuilder."<init>":()V
7: astore_1
8: new #22 // class java/lang/String
11: dup
12: invokespecial #24 // Method java/lang/String."<init>":()V
15: astore_2
16: iconst_0
17: istore_3
18: goto 47
21: new #19 // class java/lang/StringBuilder
24: dup
25: ldc #25 // String
27: invokespecial #27 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
30: iload_3
31: invokevirtual #30 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
34: invokevirtual #34 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
37: astore_2
38: aload_1
39: aload_2
40: invokevirtual #38 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
43: pop
44: iinc 3, 1
47: iload_3
48: sipush 1000
51: if_icmplt 21
54: return
publicstaticvoidmain(java.lang.String[])抛出java.io.IOException;
代码:
0:new#19//类java/lang/StringBuilder
3:dup
4:invokespecial#21//方法java/lang/StringBuilder。”“:()V
7:astore_1
8:new#22//class java/lang/String
11:dup
12:invokespecial#24//方法java/lang/String。“:()V
15:astore_2
16:iconst_0
17:istore_3
18:转到47
21:new#19//class java/lang/StringBuilder
24:dup
25:ldc#25//String
27:invokespecial#27//方法java/lang/StringBuilder。”“:(Ljava/lang/String;)V
30:iload_3
31:invokevirtual#30//方法java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
34:invokevirtual#34//方法java/lang/StringBuilder.toString:()Ljava/lang/String;
37:astore_2
38:aload_1
39:aload_2
40:invokevirtual#38//方法java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
43:流行音乐
44:iinc 3,1
47:iload_3
48:sipush 1000
51:if_icmplt 21
54:返回
我们关心的指令是从21到40。在21中,创建了第二个StringBuilder,我们将稍后再讨论它
在25中,我们看到有一个ldc,这意味着一个文本被推送到堆栈中,在本例中,它是文本字符串“”
然后真正的魔法发生了。调用第二个StringBuilder的构造函数,它将堆栈中的文本作为参数。然后使用iload_3从局部变量数组加载int i,然后调用第二个StringBuilder的append方法将i附加到它,然后调用toString。使用astore_2和aload_1存储toString调用的返回值,加载第一个StringBuilder,然后再次加载字符串。最后,调用第一个StringBuilder的append方法将新字符串添加到StringBuilder
因此,在每个循环中都会创建一个新的StringBuilder,因为每次使用“+i”时,都必须创建一个StringBuilder来连接字符串和int。此外,中间StringBuilder的toString方法将创建一个新字符串,因此总共有2000个对象
更好的版本如下所示:
for (int i = 0; i < 1000; i++) {
sb.append(' ');
sb.append(i);
}
for(int i=0;i<1000;i++){
某人附加(“”);
某人(i);
}
这将创建以下字节码:
public static void main(java.lang.String[]) throws java.io.IOException;
Code:
0: new #19 // class java/lang/StringBuilder
3: dup
4: invokespecial #21 // Method java/lang/StringBuilder."<init>":()V
7: astore_1
8: new #22 // class java/lang/String
11: dup
12: invokespecial #24 // Method java/lang/String."<init>":()V
15: astore_2
16: iconst_0
17: istore_3
18: goto 37
21: aload_1
22: bipush 32
24: invokevirtual #25 // Method java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
27: pop
28: aload_1
29: iload_3
30: invokevirtual #29 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
33: pop
34: iinc 3, 1
37: iload_3
38: sipush 1000
41: if_icmplt 21
44: return
publicstaticvoidmain(java.lang.String[])抛出java.io.IOException;
代码:
0:new#19//类java/lang/StringBuilder
3:dup
4:invokespecial#21//方法java/lang/StringBuilder。”“:()V
7:astore_1
8:new#22//class java/lang/String
11:dup
12:invokespecial#24//方法java/lang/String。“:()V
15:astore_2
16:iconst_0
17:istore_3
18:转到37
21:aload_1
22:32
24:invokevirtual#25//方法java/lang/StringBuilder.append:(C)Ljava/lang/StringBuilder;
27:流行音乐
28:aload_1
29:iload_3
30:invokevirtual#29//方法java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
33:流行音乐
34:iinc 3,1
37:iload_3
38:sipush 1000
41:if_icmplt 21
44:返回
我们可以看到,现在只有一个StringBuilder,它的append方法被调用了两次,所以这里没有分配内存,这应该更好。如果我们编译这段代码并查看生成的字节码,我们可以准确地检查它
public static void main(java.lang.String[]) throws java.io.IOException;
Code:
0: new #19 // class java/lang/StringBuilder
3: dup
4: invokespecial #21 // Method java/lang/StringBuilder."<init>":()V
7: astore_1
8: new #22 // class java/lang/String
11: dup
12: invokespecial #24 // Method java/lang/String."<init>":()V
15: astore_2
16: iconst_0
17: istore_3
18: goto 47
21: new #19 // class java/lang/StringBuilder
24: dup
25: ldc #25 // String
27: invokespecial #27 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
30: iload_3
31: invokevirtual #30 // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
34: invokevirtual #34 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
37: astore_2
38: aload_1
39: aload_2
40: invokevirtual #38 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
43: pop
44: iinc 3, 1
47: iload_3
48: sipush 1000
51: if_icmplt 21
54: return
publicstaticvoidmain(java.lang.String[])抛出java.io.IOException;
代码:
0:new#19//类java/lang/StringBuilder
3:dup
4:invokespecial#21//方法java/lang/StringBuilder。”“:()V
7:astore_1
8:new#22//class java/lang/String
11:dup
12:invokespecial#24//方法java/lang/String。“:()V
15:astore_2
16:iconst_0
17: