i++与++i在虚拟机层面上的骚操作:
很多人都会有这样一个理解误区:认为i++和++i是从虚拟机栈中取出i的初始值执行计算后再入栈,其实不然:
i++与++i都仅仅在局部变量表上执行+1操作,也就是说仅仅更新局部变量表。
又如int i = 1;i=i++;
这段代码在虚拟机的执行过程如下:
bpush 1将1入栈,由于i = 1有赋值操作,就会istore_1将栈顶元素,即1从栈中弹出存入局部变量表槽1的位置;接着i++会执行两步操作:1.iload将局部变量表中槽1的位置的值(1)复制到栈顶,2.直接在局部变量表槽1的位置执行+1操作,此时局部变量表槽1的位置的值更新为2;最后,由于i=i++有赋值操作,就会istore_1将栈顶元素,即1从栈中弹出存入局部变量表槽1的位置(1);
既然有i++那么必然有++i,例如int i = 1;i=++i;执行过程:
bpush 1将1入栈,由于i = 1有赋值操作,就会istore_1将栈顶元素,即1从栈中弹出存入局部变量表槽1的位置;接着i++会执行两步操作:1.直接在局部变量表槽1的位置执行+1操作,此时局部变量表槽1的位置的值更新为2,2.iload_1将局部变量表中槽1的位置的值(2)复制到栈顶;最后,由于i=i++有赋值操作,就会istore_1将栈顶元素,即1从栈中弹出存入局部变量表槽1的位置(2);
再来一个深入的例子:
int i = 0;
i = 5+ i++;
执行过程如下:
bpush 1将0入栈,由于i = 0有赋值操作,就会istore_1将栈顶元素,即1从栈中弹出存入局部变量表槽1的位置;然后,iconst_5将5入栈,至于i++的两个操作(可以看成原子操作),1.iload_1先将将局部变量表中槽1的位置的值(0)复制到栈顶,2.直接在局部变量表槽1的位置执行+1操作,此时局部变量表槽1的位置的值更新为1;最后iadd从栈中弹出两个操作数5和0相加得到5,入栈,由于i = 5+ i++;有赋值操作,istore_1将栈顶元素,即5从栈中弹出存入局部变量表槽1的位置(5),此时槽1中1变为5;
对应的++i:
int i = 0;
i = 5+ ++i;
执行过程如下:
bpush 1将0入栈,由于i = 0有赋值操作,就会istore_1将栈顶元素,即1从栈中弹出存入局部变量表槽1的位置;然后,iconst_5将5入栈,至于i++的两个操作(可以看成原子操作),1.直接在局部变量表槽1的位置执行+1操作,此时局部变量表槽1的位置的值更新为1,2.iload_1先将将局部变量表中槽1的位置的值(1)复制到栈顶;最后iadd从栈中弹出两个操作数5和1相加得到6,入栈,由于i = 5+ ++i;有赋值操作,istore_1将栈顶元素,即6从栈中弹出存入局部变量表槽1的位置(6),此时槽1中1变为6;