程序目的
从java字节码层理解,为何i = i++ 后,结果是+1 之前的数值。而i=++i 后,结果是+1 之后的值。
关键指令
iload_<n> :从局部变量表获取值,并压入操作数栈。 istore_<n> :出栈,然后存储到局部变量表。
i++示例源码
public class TestIPulsPlus {
public static void main(String[] args) {
int i = 8;
i = i++;
System.out.println(i);
}
}
i++执行结果:
8
使用jclasslib 查看i++ 字节码
找到main方法的Code区:
图:i=i++字节码
字节码解读
0 bipush 8 把数值8压入操作数栈,压栈前转为int类型。 2 istore_1 8出栈,存到编号为1的局部变量表。
图:编号为1的局部变量为1
以上两行指令,完成了int i = 8; 这行代码。
3 iload_1 从局部变量表,获取int值8。然后压到操作数栈。 4 iinc 1 by 1 把局部变量表中的i,进行+1操作。此时栈里面数值是8,局部变量表中i为9。 7 istore_1 8出栈,存到编号为1的局部变量表。也就是赋值给i变量。局部变量表的i值从9变为8。
接下来,解读i=++i 的字节码
图:i=++i;字节码
++i示例源码
public class TestIPulsPlus {
public static void main(String[] args) {
int i = 8;
i = ++i;
System.out.println(i);
}
}
执行结果为:
9
i=++i 字节码解读
0 bipush 8 把数值8压入操作数栈,压栈前转为int类型。 2 istore_1 8出栈,存到编号为1的局部变量表。
图:编号为1的局部变量为1
以上两行指令,完成了int i = 8; 这行代码。
3 iinc 1 by 1 把局部变量表中的i,进行+1操作。此时,局部变量表中i为9。 6 iload_1 从局部变量表,获取int值9。然后压到操作数栈。 7 istore_1 9出栈,存到编号为1的局部变量表。也就是赋值给i变量。
结论
i=i++ 和i=++i ,第3、4行位置是相反的。 i++ 是先执行iload_1 ,再执行iinc 1 by 1 。 iload_1 :从局部变量表,获取int值8。然后压到操作数栈。 iinc 1 by 1 :把局部变量表中的i,进行+1操作。此时栈里面数值是8,局部变量表中i为9。 istore_1 时,获取的是栈中的8,所以最后结果为8 。
而++i ,是先执行iinc 1 by 1 ,再执行iload_1 。 iinc 1 by 1 : 把局部变量表中的i,进行+1操作。此时,局部变量表中i为9。 iload_1 :从局部变量表,获取int值9。然后压到操作数栈。 istore_1 时,获取的是栈中的9,所以最后结果为9 。
参考
Chapter?6.?The Java Virtual Machine Instruction Set
|