Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java StringBuilder中append的参数是新的字符串对象吗?它会被垃圾收集吗?_Java_String_Garbage Collection_Stringbuilder - Fatal编程技术网

Java StringBuilder中append的参数是新的字符串对象吗?它会被垃圾收集吗?

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

在下面的代码中,当它到达注释时,如果GC没有运行,将创建大约1000个对象(根据OCA手册),修改
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: