以前对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
a = a++
测试代码:
public class test{
public static void main(String[] args) {
int a=1;
a = a++;
System.out.println(a);
}
}
反编译结果:
反编译结果解释:
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
a = ++a
测试代码:
public class test{
public static void main(String[] args) {
int a=1;
a = ++a;
System.out.println(a);
}
}
反编译结果:
反编译结果解释:
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 栈顶:2
11: invokevirtual #3 取栈顶元素输出2 // Method java/io/PrintStream.println:(I)V
14: return