Java中拼接字符串方式(+、StringBuilder/StringBuffer)分析

字符串是 Java 程序中最常用的數據結構之一。在 Java 中 String 類已經重載了"+",字符串可以直接使用"+"進行連接,也可以用StringBuilder/StringBuffer(StringBuilder是J2SE5 及以上版本提供,以前的版本使用 StringBuffer 類)。哪種方式更好呢?如下:

public class TestString {
    public static void main(String[] args) {
        String str1 = "str1";
        String str2 = "str2" + str1 + "OK" + 1;
        System.out.println(str2);
    }
}
``

編譯`javac TestString.java`,反編譯字節碼`javap -c TestString.class`:

```Compiled from "TestString.java"
public class TestString {
  public com.swsc.solarverse.TestString();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String str1
       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 str2
      16: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      19: iconst_1
      20: invokevirtual #7                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      23: invokevirtual #8                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      26: astore_2
      27: getstatic     #9                  // Field java/lang/System.out:Ljava/io/PrintStream;
      30: aload_2
      31: invokevirtual #10                 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      34: return
}

可以看出,字符串對象通過“+”的字符串拼接方式,實際上是通過 StringBuilder 調用 append() 方法實現的,拼接完成之後調用 toString() 得到一個 String 對象 。但是,在循環內使用“+”進行字符串的拼接的話,會在循環體內循環創建StringBuilder 對象,如果直接使用StringBuilder拼接則不會。如:

public class TestString {
    public static void main(String[] args) {
        String str = "";
        for(int i = 0; i < 3; i++){
            str = str + i;
        }
    }
}

編譯javac TestString.java,反編譯字節碼javap -c TestString.class

Compiled from "TestString.java"
public class TestString {
  public com.swsc.solarverse.TestString();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String
       2: astore_1
       3: iconst_0
       4: istore_2
       5: iload_2
       6: iconst_3
       7: if_icmpge     35
      10: new           #3                  // class java/lang/StringBuilder
      13: dup
      14: invokespecial #4                  // Method java/lang/StringBuilder."<init>":()V
      17: aload_1
      18: invokevirtual #5                  // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
      21: iload_2
      22: invokevirtual #6                  // Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
      25: invokevirtual #7                  // Method java/lang/StringBuilder.toString:()Ljava/lang/String;
      28: astore_1
      29: iinc          2, 1
      32: goto          5
      35: return
}

注意:使用 “+” 進行字符串拼接會產生大量的臨時對象的問題在 JDK9 中得到了解決。在 JDK9 當中,字符串相加 “+” 改爲了用動態方法makeConcatWithConstants() 來實現,而不是大量的 StringBuilder 了。這個改進是 JDK9 的 JEP 280open in new window 提出的,這也意味着 JDK 9 之後,可以放心使用“+” 進行字符串拼接了。Java9後String 的底層實現由 char[] 改成了 byte[]。

Compiled from "TestString.java"
public class TestString {

  public static void main(java.lang.String[]);
    Code:
       0: ldc           #2                  // String
       2: astore_1
       3: iconst_0
       4: istore_2
       5: iload_2
       6: iconst_3
       7: if_icmpge     24
      10: aload_1
      11: iload_2
      12: invokedynamic #3,  0              // InvokeDynamic #0:makeConcatWithConstants:(Ljava/lang/String;I)Ljava/lang/String;
      17: astore_1
      18: iinc          2, 1
      21: goto          5
      24: return
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章