String str = "test";
str = str + "test2";
str = str + "test3";
str = str + "test4";
str = str + "test5";
上面的代码将创建多少个对象,以及有多少对象可用于垃圾回收?将创建多少个对象以及将有多少对象可用于垃圾回收?
有人能解释一下吗?
String str = "test";
str = str + "test2";
str = str + "test3";
str = str + "test4";
str = str + "test5";
上面的代码将创建多少个对象,以及有多少对象可用于垃圾回收?将创建多少个对象以及将有多少对象可用于垃圾回收?
有人能解释一下吗?
关于字符串操作,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,追加字符串,并继续。
这样的代码,特别是在循环内部使用时,会冲高垃圾收集器。
有三种更好的方法来做到这一点:
使用CONCAT代替:
String str = "test";
str = str.concat("test2");
str = str.concat("test3");
str = str.concat("test4");
str = str.concat("test5");
使用串联的单行线,这将创建一个单一的StringBuilder。请记住每个;将创建另一个StringBuilder。请注意,在下面的常量字符串串联中,Java编译器将创建一个字符串。但是,如果添加一个或多个字符串变量,则将创建StringBuilder。
String str = "test" + "test2" + "test3" + "test4" + "test5";
创建一个StringBuilder自己,做串联,并REUSE 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个不同的StringBuilders将被创建。在最终的String之后,所有的StringBuilders都将被收集。
多少对象将被创建
在运行时,如图4所示,即str
四个计算值,但不包括其中来自于常量池的初始值。
以及有多少对象可用于垃圾回收?
在该代码的末尾但在str
超出范围之前,三个即str
的三个中间值。
请注意,我计数Strings
。每个String
将有一个关联char[]
这是另一个对象。
但是,如果周围的代码使得JVM可以确定str
不能在这些代码行之间改变,则它可能分别低至1和0。
我想'String str =“test”;'也会在String常量池中创建一个对象,它位于JVM的堆内存中。所以没有。的对象将是5. –
@RohitGaikwad但在运行时不执行此代码。它发生在课程加载时间。 – EJP
请参阅http://stackoverflow.com/questions/10443492/how-many-objects-are-created,但该问题已过了几年,可能已过时。 – ajb
查看http://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.18.1,似乎没有明确的答案 - 不同的实现可能会有所不同的东西。 – ajb