String對象是不可變的,本文通過String的拼接翻譯成的字節(jié)碼,查看具體的原理,并且和顯示的使用StringBuilder進行拼接生成的字節(jié)碼進行對比,總結(jié)基本的使用原則。
String對象是不可變的,對一個String進行處理,無論是進行追加,轉(zhuǎn)換大小寫之類的,都會生成一個新的字符串。同時不可變性會帶來一定的效率問題。下面通過一個追加字符串的字節(jié)碼來了解下
Stringwho="arthinking";Stringstr1="what"+"is"+who+"?";System.out.println(str1);
編譯成字節(jié)碼,查看下具體的執(zhí)行流程 。進入編譯生成的Class所在目錄,執(zhí)行 javap -c StringTest,得到如下的JVM字節(jié)碼:

其中的dup和invokevirtural相當(dāng)于Java虛擬機上的匯編語言,編譯器自動引入了java.lang.StringBuilder類。從紅色的框框標識可以看到,編譯器創(chuàng)建了一個StringBuilder對象,用于構(gòu)造最終的String,并為每個字符串調(diào)用一次StringBuilder的append()方法,最后調(diào)用了toString()生成結(jié)構(gòu),并使用astore_2命令存為s。
明確的使用StringBuilder對象能夠避免產(chǎn)生過多的StringBuilder對象
在循環(huán)里使用+隱式的拼接字符串
publicStringimplicit(String[]fields){Stringresult="";for(inti=0;i
在循環(huán)里顯示的使用StringBuilder的append方法拼接字符串
publicStringexplicit(String[]fields){StringBuilderresult=newStringBuilder();for(inti=0;i
同樣,進入編譯生成的Class所在目錄,執(zhí)行 javap -c StringTest,得到JVM字節(jié)碼,下面是implicit方法的:

從第8行到第35行構(gòu)成了一個循環(huán)體可以看出,StringBuilder是在循環(huán)體內(nèi)構(gòu)造的,這意味著每經(jīng)過一次循環(huán),就會創(chuàng)建一個新的StringBuilder對象 。
下面是explicit方法的:

可以看到,這里只生成了一個StringBuilder對象,還可以為StringBuilder對象預(yù)先為其指定大小,如果已經(jīng)知道最終的字符串大概有多長,這樣可以避免多次給StringBuilder重新分配緩沖。
總結(jié):
當(dāng)為一個類編寫toString()方法時,如果字符串操作比較簡單,可以信賴編譯器,它會合理的為你構(gòu)造最終的字符串結(jié)果,如果要在toString()方法中使用循環(huán),最好自己創(chuàng)建一個StringBuilder對象。執(zhí)行例如 append(a + ":" + b),編譯器會掉入陷阱,從而另外創(chuàng)建一個StringBuilder對象處理括號內(nèi)的字符串操作。
原文 :?http://www.itzhai.com/difference-immutable-string-objects-using-stringbuffer-using-connection-string-handling-of-the-jvm.html