i++++i
i-=-1i+=1
以上的四句代码,问那句的执行速度更快?
对于C/C++程序员来说,可能首先想到的就是i++和++i要比其他两者要快一些,但是在Java中是不是这样的呢?
我们可以对他进行一些分析,首先当然想到的是对这些语句利用Java的System.currentTimeMillis()计算单个语句运行很多次(如10亿次)后的时间,然后作比较.
例如这样:
测试环境:(1)Windows XP sp3 (2)JDK "1.6.0_07" Client VM (build 10.0-b23, mixed
mode, sharing)
CodepublicclassIncrement {publicintpreIncrement() {inti=0;++i;returni;
}publicintpostIncrement() {inti=0;
i++;returni;
}publicintnegative() {inti=0;
i-=-1;returni;
}publicintplusEquals() {inti=0;
i+=1;returni;
}publicstaticvoidmain(String[] args) {
Increment in&#61;newIncrement();longstart&#61;System.currentTimeMillis();for(inti&#61;0; i<1000000000;
i&#43;&#43;) {
in.preIncrement();
}
System.out.println("preIncrement:"&#43;(System.currentTimeMillis()-start));
start&#61;System.currentTimeMillis();for(inti&#61;0; i<1000000000;
i&#43;&#43;) {
in.postIncrement();
}
System.out.println("postIncrement:"&#43;(System.currentTimeMillis()-start));
start&#61;System.currentTimeMillis();for(inti&#61;0; i<1000000000;
i&#43;&#43;) {
in.negative();
}
System.out.println("negative:"&#43;(System.currentTimeMillis()-start));
start&#61;System.currentTimeMillis();for(inti&#61;0; i<1000000000;
i&#43;&#43;) {
in.plusEquals();
}
System.out
.println("plusEquals:"&#43;(System.currentTimeMillis()-start));
}
}
运行结果&#xff0c;发现四次结果都不一样但是差别极其微小&#xff0c;如图:
但是这样我们是不是就可以说&#xff0c;这四个语句的运行在Java中是有差别或者是无差别的呢&#xff1f;当然不能这样去说&#xff0c;这个程序的具体运行还受限于当前机器的所运行的其他程序以及JVM中的JIT引擎对执行代码的优化等。
其实一个比较合理的办法利用Javap反汇编这个文件&#xff0c;去看看反汇编后各个方法所生成的字节码&#xff0c;由于JVM在运行的时候就是执行这些中间代码&#xff0c;所以比较能够说明问题.
然后我运行javap –c –v
com.jni.test.tracker.object.Increment去反汇编这个代码&#xff0c;得到了preIncrement&#xff0c;postIncrement&#xff0c;negative&#xff0c;plusEquals方法各自的字节码如下&#xff1a;
public intpreIncrement();
Code:
Stack&#61;1, Locals&#61;2, Args_size&#61;1
0: iconst_01: istore_12: iinc 1, 1
5: iload_16: ireturn
LineNumberTable:
line5: 0line6: 2line7: 5LocalVariableTable:
Start Length Slot Name Signature0 7 0 this Lcom/jni/test/tracker/object/Increment;2 5 1i Ipublic intpostIncrement();
Code:
Stack&#61;1, Locals&#61;2, Args_size&#61;1
0: iconst_01: istore_12: iinc 1, 1
5: iload_16: ireturn
LineNumberTable:
line11: 0line12: 2line13: 5LocalVariableTable:
Start Length Slot Name Signature0 7 0 this Lcom/jni/test/tracker/object/Increment;2 5 1i Ipublic intnegative();
Code:
Stack&#61;1, Locals&#61;2, Args_size&#61;1
0: iconst_01: istore_12: iinc 1, 1
5: iload_16: ireturn
LineNumberTable:
line17: 0line18: 2line19: 5LocalVariableTable:
Start Length Slot Name Signature0 7 0 this Lcom/jni/test/tracker/object/Increment;2 5 1i Ipublic intplusEquals();
Code:
Stack&#61;1, Locals&#61;2, Args_size&#61;1
0: iconst_01: istore_12: iinc 1, 1
5: iload_16: ireturn
LineNumberTable:
line23: 0line25: 2line26: 5LocalVariableTable:
Start Length Slot Name Signature0 7 0 this Lcom/jni/test/tracker/object/Increment;2 5 1 i I
令人惊讶的是&#xff0c;虽然这四个方法是不一样的&#xff0c;但是经过Java编译器优化后&#xff0c;我们发现生成的四个方法的bytecode实际都是一样的。
下面简单讲解一下这几句bytecode
iconst_0:将int类型的值0压入栈
istore_1: 从栈中弹出int类型值&#xff0c;然后将其存到位置为0的局部变量中
iinc 1,1 : 为局部变量中位置为1的int数 加1
iload_1 : 将局部变量中位置为1的int变量入栈
ireturn : 从栈中弹出int类型值。