java编译器对代码的优化
今天公司的一位同学提到了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,毕竟这样可以加深你对性能的理解,而且不依赖特定的编译器优化。