“+=”和append的區別
“+=”和append的區別是面試中出現頻率較高的一個題目了,下面我們就來分析一下這兩者的區別吧。
首先看一下這段程式碼的結果:
String s1 = "a"; String s2 = s1 + "b"; System.out.println(s2 == "ab"); // false
輸出結果是false
;
javap將其反編譯之後的結果如下:
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: getstatic#8// Field java/lang/System.out:Ljava/io/PrintStream; 26: aload_2 27: ldc#9// String ab 29: if_acmpne36 32: iconst_1 33: goto37 36: iconst_0 37: invokevirtual #10// Method java/io/PrintStream.println:(Z)V 40: return
根據結果我們可以看到:
- 虛擬機器開始是定義了一個字串”a“將其入棧;
- 然後new了一個StringBuilder物件,將”a“封裝到Sb物件中;
- 之後用StringBuilder的append()方法來完成"a"和"b"的拼接;
所以這裡的"ab"字串本質上是一個StringBuilder物件,所以再去跟常量"ab"
去比較的話會是false;
這樣看來用"+"和append效率似乎是一樣的,並沒有像網上說的那樣”+“操作比append()更消耗效能。
那下面我們來看一下這兩者在迴圈中是什麼結果:
首先是”+=“操作:
public static void main(String[] args) { String[] arr = new String[]{"a","b","c"}; String result = ""; for (int i = 0 ; i < arr.length; i ++) { result += arr[i]; } System.out.println(result); }
反編譯結果如下:
public common.AppendAndAdd(); Code: 0: aload_0 1: invokespecial #1// Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: iconst_3 1: anewarray#2// class java/lang/String 4: dup 5: iconst_0 6: ldc#3// String a 8: aastore 9: dup 10: iconst_1 11: ldc#4// String b 13: aastore 14: dup 15: iconst_2 16: ldc#5// String c 18: aastore 19: astore_1 20: ldc#6// String 22: astore_2 23: iconst_0 24: istore_3 25: iload_3 26: aload_1 27: arraylength 28: if_icmpge58 43,134% 31: new#7// class java/lang/StringBuilder 34: dup 35: invokespecial #8// Method java/lang/StringBuilder."<init>":()V 38: aload_2 39: invokevirtual #9// Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 42: aload_1 43: iload_3 44: aaload 45: invokevirtual #9// Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 48: invokevirtual #10// Method java/lang/StringBuilder.toString:()Ljava/lang/String; 51: astore_2 52: iinc3, 1 55: goto25 58: getstatic#11// Field java/lang/System.out:Ljava/io/PrintStream; 61: aload_2 62: invokevirtual #12// Method java/io/PrintStream.println:(Ljava/lang/String;)V 65: return
可以看到從25: iload_3
和55: goto25
兩句構成了一個迴圈,而31: new#7// class java/lang/StringBuilder
建立StringBuilder物件語句在迴圈內,所以會建立多個
SB物件;
下面我們把程式碼改為append()實現:
public static void main(String[] args) { String[] arr = new String[]{"a","b","c"}; StringBuilder result = new StringBuilder(); for (int i = 0 ; i < arr.length; i ++) { result.append(arr[i]); } System.out.println(result); }
反編譯後:
public static void main(java.lang.String[]); Code: 0: iconst_3 1: anewarray#2// class java/lang/String 4: dup 5: iconst_0 85,768% 6: ldc#3// String a 8: aastore 9: dup 10: iconst_1 11: ldc#4// String b 13: aastore 14: dup 15: iconst_2 16: ldc#5// String c 18: aastore 19: astore_1 20: new#6// class java/lang/StringBuilder 23: dup 24: invokespecial #7// Method java/lang/StringBuilder."<init>":()V 27: astore_2 28: iconst_0 29: istore_3 30: iload_3 31: aload_1 32: arraylength 33: if_icmpge50 36: aload_2 37: aload_1 38: iload_3 39: aaload 40: invokevirtual #8// Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 43: pop 44: iinc3, 1 47: goto30 50: getstatic#9// Field java/lang/System.out:Ljava/io/PrintStream; 53: aload_2 54: invokevirtual #10// Method java/io/PrintStream.println:(Ljava/lang/Object;)V 57: return
可以發現在由30: iload_3
和47: goto30
構成的迴圈體內沒有new操作,而是放到了迴圈外部
20: new#6// class java/lang/StringBuilder
由此得出,在迴圈時使用+= 會建立多個StringBuilder物件,而使用append(),只會建立一個。
所以我們在平時寫程式碼的時候一定注意,不要再迴圈中使用+=操作,效率很低的。