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