Java中字符串String的+和+=及循環(huán)操作String原理詳解
String對象是不可變的:意思就是無論是對String的新增或修改,出現(xiàn)一個全新的String內容時,都意味著誕生了一個新的對象。但是如果內容不變的話,增加的只是對象的引用而已。
例如:
String a = "ljh"; String b = "ljh"; String c = "ljh"; System.out.println(a==b); System.out.println(b==c);
結果都是true
但是這種不可變性會產生一些性能上的問題,所以JVM對String對象重載“+”“+=”進行了一些優(yōu)化
操作符“+”可以用來連接String
String aaa = "ljh"; String bbb = "big"; String ccc = aaa+bbb+"aaaa";
在jdk8中,上述代碼中在底層其實是編譯器擅自調用了StringBuilder類進行+的操作,主要原因是StringBuilder的append()更加高效,我們來看一下字節(jié)碼。
public static void main(java.lang.String[]);
Code:
0: ldc #2 // String ljh
2: astore_1
3: ldc #3 // String big
5: astore_2
6: new #4 // class java/lang/StringBuilder
9: dup
10: invokespecial #5 // Method java/lang/StringBuilder."<init>":()V
13: aload_1
14: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
17: aload_2
18: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
21: ldc #7 // String aaaa
23: invokevirtual #6 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
26: invokevirtual #8 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
29: astore_3
30: return可以看出一共有四個對象,分別是三個String 和一個StringBuilder
我們再來看一下+=
String a = "aaa"; a += "bbb";
字節(jié)碼如下
Code:
0: ldc #2 // String aaa
2: astore_1
3: new #3 // class java/lang/StringBuilder
6: dup
7: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
10: aload_1
11: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
14: ldc #6 // String bbb
16: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_1
23: return
可以看出先創(chuàng)建了一個“aaa”字符串,然后當a遇到+=時,創(chuàng)建了一個StringBuilder對象,并append了aaa字符串。之后創(chuàng)建了一個“bbb”對象,然后append了bbb字符串,最后調用StringBuilder的toString方法。
接下來再看看循環(huán)中調用+=會是什么樣子
String a = "aaa";
a += "bbb";
for(int i=0;i<5;i++){
a+="ccc";
}Code:
0: ldc #2 // String aaa
2: astore_1
3: new #3 // class java/lang/StringBuilder
6: dup
7: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
10: aload_1
11: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
14: ldc #6 // String bbb
16: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_1
23: iconst_0
24: istore_2
25: iload_2
26: iconst_5
27: if_icmpge 56
30: new #3 // class java/lang/StringBuilder
33: dup
34: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
37: aload_1
38: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
41: ldc #8 // String ccc
43: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
46: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
49: astore_1
50: iinc 2, 1
53: goto 25
56: return
可以看出先創(chuàng)建String對象aaa,之后創(chuàng)建StringBuilder并初始化StringBuilder append aaa,然后創(chuàng)建bbb對象,并append( bbb),然后我們發(fā)現(xiàn)在循環(huán)中依舊創(chuàng)建了一個新的StringBuilder,也就是沒經過一次循環(huán)都要創(chuàng)建一個新的StringBuilder對象。
這時我們做一個優(yōu)化,提前創(chuàng)建StringBuilder對象
String a = "aaa";
a += "bbb";
StringBuilder sb = new StringBuilder(a);
for(int i=0;i<5;i++){
sb.append("ccc");
}Code:
0: ldc #2 // String aaa
2: astore_1
3: new #3 // class java/lang/StringBuilder
6: dup
7: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
10: aload_1
11: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
14: ldc #6 // String bbb
16: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: invokevirtual #7 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: astore_1
23: new #3 // class java/lang/StringBuilder
26: dup
27: aload_1
28: invokespecial #8 // Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
31: astore_2
32: iconst_0
33: istore_3
34: iload_3
35: iconst_5
36: if_icmpge 52
39: aload_2
40: ldc #9 // String ccc
42: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
45: pop
46: iinc 3, 1
49: goto 34
52: return
可以看出循環(huán)體跳回34行,并不會不斷地創(chuàng)建新的StringBuilder,大大提高了效率和減小了垃圾數量!,所以我們要注意自己的寫法!避免無謂的消耗
總結
到此這篇關于Java中字符串String的+和+=及循環(huán)操作String原理的文章就介紹到這了,更多相關Java字符串String+和+=內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot2 整合FreeMarker實現(xiàn)頁面靜態(tài)化示例詳解
這篇文章主要介紹了SpringBoot2 整合FreeMarker實現(xiàn)頁面靜態(tài)化示例詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-07-07
SpringBoot實現(xiàn)返回值數據脫敏的步驟詳解
這篇文章主要給大家介紹一下SpringBoot實現(xiàn)返回值數據脫敏的步驟,文章通過代碼示例介紹的非常詳細,具有一定的參考價值,需要的朋友可以參考下2023-07-07
httpclient的disableConnectionState方法工作流程
這篇文章主要為大家介紹了httpclient的disableConnectionState方法工作流程源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-11-11
Java泛型模擬scala實現(xiàn)自定義ArrayList方式
這篇文章主要介紹了Java泛型模擬scala實現(xiàn)自定義ArrayList方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-10-10

