一篇文章带你从java字节码层理解i++和++i
程序目的
从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++;
// 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++;
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变量。
参考
Chapter 6. The Java Virtual Machine Instruction Set
总结
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。
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!
相关文章
关于SpringBoot配置文件application.properties的路径问题
这篇文章主要介绍了关于SpringBoot配置文件application.properties的路径问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2022-08-08
浅析Spring boot 中 logback 配置<springPropert
这篇文章主要介绍了浅析Spring boot 中 logback 配置<springProperty> 读取application.properties 中的属性,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下2023-02-02
Map映射LinkedHashSet与LinkedHashMap应用解析
这篇文章主要为大家介绍了Map映射LinkedHashSet与LinkedHashMap的应用解析,有需要的朋友可以借鉴参考下,希望能够有所帮助祝大家多多进步2022-03-03


最新评论