1. 程式人生 > >java String常量池與字串拼接效能優化

java String常量池與字串拼接效能優化

----String常量池----
1.常量池中的物件從哪裡來的?

String s1="hanhan";
String s2="hanhan";
System.out.println(s1==s2);//true

當我們建立String物件採用字面量形式時,JVM首先會對這個字面量進行檢查,如果常量池中存放有該字面量,則直接使用,否則建立新的物件並將其引用放入常量池中。

String s1="han";
String s2=new String("han");
System.out.println(s1==s2);//false

當我們通過new來建立一個字串時,JVM就不會去常量池中找,而是直接在堆中新建一個物件。如果我們想把new的物件也放在常量池中,可以呼叫方法inner();

String s1="guoguo";
String s2=new String("guoguo").intern();
System.out.println(s1==s2);//true

當我們new新的物件時,之後再呼叫intern()方法,如果沒有把s2重新引用則s2仍為原來的物件,此時s1不等於s2,若重新引用常量池中的物件,則s1等於s2
這裡寫圖片描述

String s1="gh";
String s2=new String("gh");
s2.intern();
System.out.println(s1==s2);//false;
s2=s2.intern();
System.out.println(s1==s2);//true;

2.常量池中存的是物件還是引用?
常量池中存的是對物件的引用,儲存於JVM的方法區中,而且引用的物件儲存於堆中。
3.常量池中的物件會被GC回收嗎?
當常量池中的引用沒有被任何變數引用時,就會被GC回收!
這裡寫圖片描述

----字串拼接----
1.字串拼接的內部實現

String s1="a"+"b"+"c";

正常情況下,執行宣告s1程式碼會生成3個物件,即物件a、物件ab、物件abc,其中物件a和物件ab都是中間的臨時變數,最後的物件abc才賦值給了s1。因此在使用字串拼接的時候,拼接的數量越多,效能越低!
但是java編譯器在編譯的時候做了優化,在編譯時新建一個物件StringBuilder來拼接,這樣就避免了產生很多臨時物件,從而提升了效能!但是一下程式碼效能就低下:

String s="";
for(int i=0;i<length;i++){
   s+=i;
}

之所以低下的原因是因為迴圈內,每次都在做字串拼接,每次都在產生一個StringBuilder物件,造成記憶體的浪費!因此這種錯誤要儘量避免,稍做以下優化即可完美改造:

String s="";
StringBuilder sb=new StringBuilder();
for(int i=0;i<length;i++){
    sb.append(i);
}

以上程式碼通過在迴圈為new一個StringBuilder物件來拼接,這樣就避免了迴圈中建立物件了!

2.字串拼接的效能優化
通過以上案例,我們就已經知道了字串拼接時儘量使用StringBuilder或者StringBuffer物件,特別時迴圈中的拼接!

3.StringBuilder與StringBuffer的區別
兩者的共同點都是建立一個字串緩衝區,然後呼叫相關方法操作字串!不同點就是StringBuilder是非同步的,而StringBuffer是同步的,因此StringBuilder執行效率更高,在不需要同步的情況下優先使用StringBuilder,否則使用StringBuffer來保證資料的同步,即多執行緒的情況下!