从虚拟机栈的角度看i++和++i
虚拟机栈
- 虚拟机栈是描述java方法执行过程的内存模型,方法的执行和返回对应着虚拟机栈中的入栈和出栈,保存的是一个一个栈帧,当前栈帧对应着当前执行的方法
- 栈帧由局部变量表,操作数栈,动态链接,返回地址和一些附加信息组成。
- 局部变量表:定义为一个数字数组,存放方法参数和定义在方法内的局部变量,这些数据类型包括基本数据类型,返回值,对象引用(reference),容量是在编译期确认下来的,
- 局部变量表的基本存储单位是槽,slot,32为以内的类型占一个slot,64位的类型占用两个槽(double和long)byte,short和char转变成int,索引为0的位置放置的是this。slot重复利用,当局部变量超过了他的作用域时,就可能会被重用。
- 操作数栈:操作数栈,在程序执行过程中,根据字节码指令,进行入栈与出栈,比如复制,求和,交换等操作,主要用于保存计算中的中间结果,同时作为计算中变量临时的存储空间。
- 栈顶缓存技术,将栈顶元素全部缓存在物理cpu的寄存器中,以降低对内存的访问次数,提升执行引擎的效率。
- 动态链接:即指向运行时常量池方法的引用,引用的目的就是为了支持当前方法的代码能够实现动态链接
- 方法重写的本质:
- 找到操作数栈顶的第一个元素所执行的对象的类型,记为c
- 如果在类型c中找到与常量中的描述符合简单名称相同的方法,则进行权限校验,如果通过则返回这个方法的直接应用,不通过则返回illegalaccesserror异常
- 否则,按照继承关系从下往上查找父类,继续第二步的搜索方法
- 如果始终没有找到,返回abstracmethoderror异常
- 方法返回地址:存放pc寄存器的值,让程序继续进行下去
好,讲了那么多,我们回归主题,怎么看待i++和++i呢,先加和后加如何理解呢?
int i = 1;
i = i++;
i = ++i;
来看一段简单的代码,上下两个i一个是1;一个是2,要理解这个问题,需要通过局部变量表和操作数栈和字节码指令来理解。
int i = 1,把 1 存入局部变量表,i = i++, 先将1 入栈,然后局部变量表的i自加,变成2,然后操作数栈出栈给局部变量表,i又变成1
i = ++i, 先把局部变量表的i自加,变成2,然后2入栈,在出栈给局部变量表,i=2.