Java的字符串連接符(+)


在Java中字符串是一個常用的東西,而其一個常用的操作是字符串的拼接,Java對此提供了一種非常直觀的操作方式——即 + 操作符。

String str0 = "a";
String str1 = str0 + "b";

如上的程序片段就實現了一個字符串的拼接,可以看到整個描述非常簡潔,一目了然。學習Java的時候,這是接觸到的第一種拼接字符串的方式,先入為主的印象會讓你在以后需要拼接字符串時第一時間想到它,但是,你會聽到大家都說:拼接大量的字符串時使用StringBuilder更好,這是為什么呢?


讓我們看看編譯器是怎么處理 + 操作符的。下面是上一個程序片段編譯后的字節碼指令:

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2 // String a
       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 b
      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_2
      23: return
}

通過閱讀這段字節碼,可以發現,我們的+拼接操作實際上被編譯器理解成了這個樣子:

String str0 = "a";
StringBuilder sb = new StringBuilder();
sb.append(str0).append("b");
String str1 = sb.toString();

中間多出來了一個StringBuilder對象,這是一個臨時對象。


假設我們現在有這樣一段程序片段:

String str0 = "a";
for (int i = 0; i < 10000; i++) {    
      str0 += "a";
}

再來看看編譯后的字節碼:

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2 // String a
       2: astore_1
       3: iconst_0
       4: istore_2
       5: iload_2
       6: sipush        10000
       9: if_icmpge     38
      12: new           #3 // class java/lang/StringBuilder
      15: dup
      16: invokespecial #4 // Method java/lang/StringBuilder."<init>":()V
      19: aload_1
      20: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      23: ldc           #2 // String a
      25: invokevirtual #5 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      28: invokevirtual #6 // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      31: astore_1
      32: iinc          2, 1
      35: goto          5
      38: return
}

5~35是我們的循環體,在循環體里面,每次拼接都會生成一個StringBuilder的臨時對象,那么這個程序片段執行下去就會產生10000個StringBuilder的臨時對象,這10000個臨時對象都是必要的嗎?顯然不是,我們可以在循環體外直接創建一個StringBuilder對象,然后在循環體中通過append方法拼接字符串,這樣就省下了創建並回收10000個臨時對象的消耗。


所以,在需要拼接大量字符串時,還是使用StringBuilder對象為好。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM