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,毕竟这样可以加深你对性能的理解,而且不依赖特定的编译器优化。