String str = "test";
str = str + "test2";
str = str + "test3";
str = str + "test4";
str = str + "test5";
将从上面的代码创建多少个对象以及有多少对象可用于垃圾回收?
有人可以解释一下吗?
答案 0 :(得分:0)
关于字符串操作,JavaC非常奇怪。例如,为什么当你执行“String + = otherString”时他们不使用String.concat?
相反,Java为每一行结束时创建一个StringBuilder(或StringBuffer,具体取决于Java版本);你已经连接了字符串。
我将您的代码放在测试程序(TCTestWin)中并从命令行调用:
javap -c TCTestWin.class
结果如下:
0: ldc #15 // String test
2: astore_1
3: new #17 // class java/lang/StringBuilder
6: dup
7: aload_1
8: invokestatic #19 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
11: invokespecial #25 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
14: ldc #28 // String test2
16: invokevirtual #30 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #34 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_1
23: new #17 // class java/lang/StringBuilder
26: dup
27: aload_1
28: invokestatic #19 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
31: invokespecial #25 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
34: ldc #38 // String test3
36: invokevirtual #30 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
39: invokevirtual #34 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
42: astore_1
43: new #17 // class java/lang/StringBuilder
46: dup
47: aload_1
48: invokestatic #19 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
51: invokespecial #25 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
54: ldc #40 // String test4
56: invokevirtual #30 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
59: invokevirtual #34 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
62: astore_1
63: new #17 // class java/lang/StringBuilder
66: dup
67: aload_1
68: invokestatic #19 // Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
71: invokespecial #25 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
74: ldc #42 // String test5
76: invokevirtual #30 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
79: invokevirtual #34 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
82: astore_1
83: return
如您所见,对于每一行,JavaC创建一个StringBuilder,追加String,然后继续。
这样的代码,特别是在循环中使用时,会抢占垃圾收集器。
有三种更好的方法:
改为使用concat:
String str = "test";
str = str.concat("test2");
str = str.concat("test3");
str = str.concat("test4");
str = str.concat("test5");
使用单行连接,这将创建一个StringBuilder。记住每个;将创建另一个StringBuilder。请注意,在下面的常量字符串的串联中,Java编译器将创建一个String。但是,如果添加一个或多个String变量,则将创建StringBuilder。
String str = "test" + "test2" + "test3" + "test4" + "test5";
自己创建一个StringBuilder,进行连接,然后重新使用 StringBuilder。这具有最佳性能,特别是在循环中执行时。
StringBuilder sb = new StringBuilder(512);
for (int i = 0; i < 10000; i++)
{
sb.setLength(0);
sb.append("test");
sb.append("test2");
sb.append("test3");
sb.append("test4");
sb.append("test5");
sb.append(i);
String s = sb.toString();
}
因此,从上面的代码中,将创建4个不同的StringBuilder。在最终的String之后,将收集所有StringBuilders。
答案 1 :(得分:0)
将创建多少个对象
在运行时,4,即str
的四个计算值,不包括来自常量池的初始值。
有多少个对象可用于垃圾回收?
在此代码的末尾,但在str
超出范围之前,有三个,即str
的三个中间值。
请注意,我正在计算Strings
。每个String
都会有一个关联的char[]
,这是另一个对象。
但是,如果周围的代码是这样的,JVM可以确定str
不能在这些代码行之间改变,那么它可以分别为1和0。