今天偶然呗问到了一个java中自增运算符的问题,涉及到了堆栈,以为挺有趣的把它记录下来。java
int i=0;
i=i++;
结果i是多少?
这是一个常常被说起的问题,答案一直五花八门。
具体测试一下以说明问题:
代码1:测试
- public class Test{
- public static void main(String[] args){
- int i=0;
- i=i++;
- System.out.println(i);
- }
- }
结果i依然是0.分析其反编译后的代码:
spa
- public static void main(java.lang.String[]);
- Code:
- 0: iconst_0 //0放到栈顶
- 1: istore_1 //把栈顶的值保存到局部变量1,也就是i中
- 2: iload_1 //把i的值放到栈顶,也就是说此时栈顶的值是0
- 3: iinc 1, 1 //注意这个指令,把局部变量1,也就是i,增长1,这个指令不会致使栈的变化,也就是说局部变量1,即i此时为1了。
- 6: istore_1 //把栈顶的值(0)保存到局部变量1,也就是让i为0了,因此最后i为0
- 7: getstatic #2;
- 10: iload_1
- 11: invokevirtual #3;
- 14: return
值得注意到是i被修改了两次,第一次是i++;i变为1,最后一次是i=0;因此结果i是0
代码2:get
- public class Test2{
- public static void main(String[] args){
- int i=0;
- int j=0;
- j=i++;
- System.out.println(i);
- System.out.println(j);
- }
- }
这个结果确定都知道,i是1,j是0.一样看反编译以后的代码: io
- public static void main(java.lang.String[]);
- Code:
- 0: iconst_0
- 1: istore_1 //i=0
- 2: iconst_0
- 3: istore_2 //j=0
- 4: iload_1 //把i的值放到栈顶,也就是说此时栈顶的值是0
- 5: iinc 1, 1 //局部变量1加1,也就是让i++了,此时i已是1了,上面说过,此指令不会致使栈变化
- 8: istore_2 //把栈顶的值(注意是0)存入局部变量2,也就是j中,因此j=0
- 9: getstatic #2;
- 12: iload_1
- 13: invokevirtual #3;
- 16: getstatic #2;
- 19: iload_2
- 20: invokevirtual #3;
- 23: return
很明显能够看出,java是先把i的值取出来放到栈顶,咱们能够认为是引入了第三个变量int k=i;而后i++,这时候i为1了,而后让j=k;也就是0.结论,i的++运算是在对j这个变量的赋值以前完成的。
代码3:编译
- public class Test3{
- public static void main(String[] args){
- int i=0;
- int j=0;
- j=++i;
- System.out.println(i);
- System.out.println(j);
- }
- }
结果你们也都知道,i=1,j=1
看操做过程: class
- public static void main(java.lang.String[]);
- Code:
- 0: iconst_0
- 1: istore_1 //i=0
- 2: iconst_0
- 3: istore_2 //j=0
- 4: iinc 1, 1 //局部变量i加1,这时候i变成1了 。
- 7: iload_1 //把i的值放到栈顶,栈顶的值是1
- 8: istore_2 //j=1
- 9: getstatic #2;
- 12: iload_1
- 13: invokevirtual #3;
- 16: getstatic #2;
- 19: iload_2
- 20: invokevirtual #3;
- 23: return
对比代码2和代码3,关键的差异就是iload_1 个iinc这两条指令的位置变了。变量