第1类问题
public void addTest1() {
//第1类问题
int i1 = 10;
i1++;
int i2 = 10;
++i2;
/**
* 对应的指令
* 0 bipush 10 10入栈
* 2 istore_1 栈顶存入slot1,此时i1=10
* 3 iinc 1 by 1 slot1加1,此时i1=11
* 6 bipush 10 10入栈
* 8 istore_2 栈顶存入slot2,此时i2=10
* 9 iinc 2 by 1 slot2加1,此时i2=11
* 12 return
*/
}
第2类问题
public void addTest2() {
//第2类问题
int i3 = 10;
int i4 = i3++;
int i5 = 10;
int i6 = ++i5;
/**
* 代码对应的指令
* 0 bipush 10 向操作数数栈推入10
* 2 istore_1 将栈顶数存入局部变量表槽位1的位置,即i3=10
* 3 iload_1 将i3压入栈顶
* 4 iinc 1 by 1 iinc表示对局部变量表索引1的位置加1(by 1),也就是i3加1,此时i3=11
* iinc应该是一个简化的指令,实际上是slot入栈,栈顶自加,栈顶出栈三条指令的合集,因为4之后
* 直接就是7了,正好隔了3个
* 7 istore_2 将栈顶的10存入slot2中,也就是i4=10
* 8 bipush 10 10入栈
* 10 istore_3 栈顶元素存入slot3,也就是i5=10
* 11 iinc 3 by 1 slot3中元素加1,此时i5=11
* 14 iload_3 slot3中元素入栈
* 15 istore 4 栈顶元素存入slot4,即i6=11
* 17 return 返回
*/
}
第3类问题
public void addTest3() {
//第3类问题
int i7 = 10;
i7 = i7++;
int i8 = 10;
i8 = ++i8;
/**
* 代码对应的指令
* 0 bipush 10 10放入栈顶
* 2 istore_1 栈顶存入slot1,即i7=10
* 3 iload_1 slot1入栈,此时栈顶为10
* 4 iinc 1 by 1 i7(局部变量表中slot1)自加1,此时i7=11
* 7 istore_1 栈顶(10)存入slot1,也就是i7又变回了10
*
* 8 bipush 10 10放到栈顶
* 10 istore_2 栈顶元素存入slot2
* 11 iinc 2 by 1 slot2自加1变为11
* 14 iload_2 slot2入栈
* 15 istore_2 栈存入slot2,此时slot2为11,即i8为11
* 16 return
*/
}
第4类问题
public void addTest4() {
//第4类问题
int i9 = 10;
int i10 = i9++ + ++ i9;
System.out.println(i9);
System.out.println(i10);
/**
* 对应的指令
* 0 bipush 10 10入栈
* 2 istore_1 栈顶(10)存入slot1(i9=10)
* 3 iload_1 slot1入栈(10)
* 4 iinc 1 by 1 slot1加1(11)
* 7 iinc 1 by 1 slot1加1(12),i9=12
* 10 iload_1 slot1入栈(12)
* 11 iadd 10+12=22
* 12 istore_2 栈顶到slot2,此时i10=22.
* 13 return
*/
}
总结
虽然不用分析指令,也能够得出正确的结果,但是遇到第3类、第4类问题的时候可能就不那么确信自己的答案了。这里分析了一下指令,心里踏实多了。总的来说自加是在局部变量表上操作的,具体实现可能还是用到了操作数栈,但是这里就我们表面上看到的就是直接在slot上进行的操作,只要不是后来被重新覆盖掉原值,不管是++i,还是i++,结果最终都是i增加了1。但是像第3类问题,因为有一个赋值操作,相当于使用栈中的值把slot中的值给覆盖了,所以会造成结果的不一致现象。