概述
i++ 与 ++i的差异,一直是计算机科学的初学者们,最为困惑的难点之一。网上也有很多大佬总结出了一些很有用的方法来区别这两个语句:i++ 是先用后自增,++i 是先自增后用。通过这种方法,我们似乎真的可以在所有出现 i++ 和 ++i 的地方披荆斩将,但它们的区别仅在于此么?
字节码探究
PS:部分专用术语解释
Java 栈帧:是用于支持虚拟机进行方法调用和方法执行的数据结构。它是虚拟机运行时数据区中的虚拟机栈的栈元素。栈帧存储了方法的局部变量表、操作数栈、动态连接和方法返回地址等信息。
操作数栈:方法的临时数据存储区,存储参与计算的数据。可存储的数据类型包括:int、long、float、double、reference、returnAddress,所有长度小于int类型的在入栈前会转换成int型。
局部变量表:一组变量值存储空间,用于存放方法参数和方法内定义的局部变量。局部变量表的容量以变量槽(Variable Slot)为最小单位。可存储的数据类型包括:boolean、byte、char、short、int、float、reference和returnAddress。
iconst_K:常量K压入栈顶
istore_A:将栈顶操作数弹出并存入局部表量表下标A处
iinc A,B:局部变量表下标A处值增加B
iload_A:将局部变量表下标A处值压入操作数栈栈顶
iadd:操作数栈栈顶前两个操作数相加,结果成为操作数栈栈顶
首先我们尝试查看 i++ 与 ++i 经过编译之后的字节码
源代码如下:
public void m1(){
int i = 0;
i ++;
++i;
}
编译后的字节码如下(请务必无视那些没有添加注释的行):
public void m1();
descriptor: ()V
flags: (0x0001) ACC_PUBLIC
Code:
stack=1, locals=2, args_size=1
0: iconst_0 # 定义常量0
1: istore_1 # 常量0保存到局部变量表下标1的位置,此位置对应于变量i
2: iinc 1, 1 # 局部变量表下标1处所对应的值,加1
5: iinc 1, 1 # 局部变量表下标1处所对应的值,加1
8: return
LineNumberTable:
line 12: 0
line 14: 2
line 16: 5
line 17: 8
Loca