从字节码看i=i++和i=++i;

对于i++

源码:

1
2
3
4
5
public int plus(){
int i=0;
i=i++;
return i;
}

字节码:

1
2
3
4
5
6
7
8
9
public int test();
Code:
0: iconst_1 //int类型 1 放入栈顶
1: istore_1 //栈顶int类型数值放入局部变量表第二个位置
2: iload_1 //将局部变量表第二个位置数据放入栈顶
3: iinc 1, 1 //将局部变量表第二个位置的元素+1
6: istore_1 //将栈顶元素放入局部变量表第二个位置
7: iload_1 //将局部变量表第二个位置的值放入栈顶
8: ireturn //将栈顶元素返回

注:局部变量表的第一个位置留给this

对于++i

1
2
3
4
5
public int plus(){
int i=0;
i=++i;
return i;
}
1
2
3
4
5
6
7
8
9
public int test();
Code:
0: iconst_1 //int类型 1 放入栈顶
1: istore_1 //栈顶int类型数值放入局部变量表第二个位置
2: iinc 1, 1 //将局部变量表第二个位置的元素+1
5: iload_1 //将局部变量表第二个位置的值放入栈顶
6: istore_1 //将栈顶元素放入局部变量表第二个位置
7: iload_1 //将局部变量表第二个位置的值放入栈顶
8: ireturn //将栈顶元素返回

解释

i++: 在字节码2,3,6,7的执行过程里,存在两个i值的情况,

​ 本地变量表存在一个 i,栈顶存在一个 i, 这是在iinc 之前发生的事

​ 然后iinc,将变量表的i增加了1,

​ 紧接着,又将栈顶的i 写入变量表的i的位置,导致修改之后的i被覆盖。

++i: 也存在两个i的情况,但是入栈的顺序不同,即:

​ ++i的第二个i是在执行iinc之后再放入栈顶

​ 此时本地变量表存在一个 i,栈顶存在一个 i,不过这是在iinc之后发生的事

​ 结果是栈顶和变量表的i都是1,再写回变量表的时候 并没有发生变化