今天公司的一位同學提到了java的一個編碼規范:拼裝字符串要用StringBuilder的append方法,而不要用String的+ 或者 +=鏈接符號
就是說,不能按照下面的方式寫
String str = "";
for (int i = 0; i < 1000; i++) {
str = str + i;
}
要按照下面的代碼進行改寫
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 1000; i++) {
sb.append(String.valueOf(i));
}
目前大部分應用使用的是jdk1.6,目前默認的編譯器其實就已經可以識別 第一種情況的字符串循環,自動會把第一種情況轉化為第二種情況,
考慮下面一段代碼
public class Test { public void test() { String str = ""; for (int i = 0; i < 1000; i++) { str = str + i; } } }
我們利用javap -verbose Test 進行反編譯,看看編譯出來的字節碼
public void test(); Code: Stack=3, Locals=3, Args_size=1 0: ldc #15; //String 2: astore_1 3: iconst_0 4: istore_2 5: goto 30 8: new #17; //class java/lang/StringBuilder 11: dup 12: aload_1 13: invokestatic #19; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String; 16: invokespecial #25; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V 19: iload_2 20: invokevirtual #28; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder; 23: invokevirtual #32; //Method java/lang/StringBuilder.toString:()Ljava/lang/String; 26: astore_1 27: iinc 2, 1 30: iload_2 31: sipush 1000 34: if_icmplt 8 37: return LineNumberTable: line 15: 0 line 17: 3 line 18: 8 line 17: 27 line 20: 37 LocalVariableTable: Start Length Slot Name Signature 0 38 0 this LTest; 3 35 1 str Ljava/lang/String; 5 32 2 i I }
主要是注釋后面,發現的確都是用StringBuilder進行了改寫
說這個問題,其實想說明的是,用語法描述的語義 經過編譯器的優化 可以轉化為另外一種語法,但是語義不變。
例如自動裝箱以及拆箱,其實只是在編譯器層面的支持。所以語法是編程語言的外在形式,經過很牛逼的編譯器,可以大大的簡化編程的復雜度,
運行時環境也就是JVM才是最語言真正的核心。
jdk1.6對很多的代碼進行了編譯期的優化,比如說鎖優化,循環優化等等。
今天早上正好看到了Objecive-C的新的語法特性,其實這些語法特性只是在編譯器層面的支持,未來編程語言語法上的發展主要還是編譯器的重大改進。
在實際編碼的時候,建議還是使用StringBuilder,畢竟這樣可以加深你對性能的理解,而且不依賴特定的編譯器優化。