以前对a++与++a的理解仅限于:
a = a++先赋值后计算,a = ++a先计算后赋值。
单从应用的角度来讲,这么简单理解是没有问题的。
这篇博客用来深入理解并测试二者真正的区别。一句话说到前头,
a = a++与a = ++a均为先计算后赋值,不同的是:
a = a++中变量先压栈,后计算,最后栈顶元素弹出赋值于a;
a = ++a中变量先计算,后压栈,最后栈顶元素弹出赋值于a。
详解如下:
先了解一些反编译的基础知识:
JVM指令详解,可以看这两篇博客:博客1 博客2
在这里我们只需要了解几个指令就行:
助记符说明 iconst_1 : 将int型(1)推送至栈顶 istore_1 : 将栈顶int型数值存入第二个本地变量。(main方法中,第一个本地变量是String[] args,第二个开始才是自己定义的变量) iload_1 : 将int型数组指定索引的值推送至栈顶(在下面的测试代码中,指的就是变量a,即把a的值压入栈顶) iinc 1, 1: 该指令第一参数为本地变量的编号,第二个参数为自增减的数量。(这里的意思就是将本地第二个变量(int型)的值+1 12345
a = a++
测试代码:
public class test{public static void main(String[] args) {int a=1;a = a++;System.out.println(a);} } 1234567
反编译结果:
反编译结果解释:
a = a++; Code: 0: iconst_1栈顶:1 a: 0 1: istore_1栈顶:已弹出该元素 a: 1 2: iload_1栈顶:1 a: 1 3: iinc 1, 1栈顶:1 a: 2 6: istore_1栈顶:已弹出该元素 a: 1 7: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream; 10: iload_1栈顶:1 11: invokevirtual #3 取栈顶元素输出1 // Method java/io/PrintStream.println:(I)V 14: return 1234567891011
a = ++a
测试代码:
public class test{public static void main(String[] args) {int a=1;a = ++a;System.out.println(a);} } 1234567
反编译结果:
反编译结果解释:
a = ++a; Code: 0: iconst_1栈顶:1 a: 0 1: istore_1栈顶:已弹出该元素 a: 1 2: iinc 1, 1栈顶:已弹出该元素 a: 2 5: iload_1 栈顶:2 a: 2 6: istore_1栈顶:已弹出该元素 a: 2 7: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;10: iload_1 栈顶:211: invokevirtual #3 取栈顶元素输出2 // Method java/io/PrintStream.println:(I)V14: return 1234567891011