i++和++i的原理分析

今天我终于了解了这两个式子在字节码指令中的具体操作原理,以前记忆这两个式子都是固定思维:i++是先进行运算再进行自增,++i是先进行自增再进行运算。但是今天发现了一个问题。

public class AutoAddTest {

    public static void main(String[] args) {
        int i = 0;
        i = i++;
        System.out.println(i);
        int j = 0;
        j = ++j;
        System.out.println(j);
    }

}

发现第一个i输出结果为0,j的结果为1。在我看来不管是i++或者++i运算之后都是会自增1的,但事实却不是这样。。。结果:
在这里插入图片描述

首先我们要知道Java虚拟机栈的内部结构,虚拟机栈是主管程序运行的,方法的执行与返回就对应着入栈与出栈,而Java虚拟机栈的基本存储单位是栈桢,每个栈桢都对应着一个方法,是一一对应的关系。
栈桢里面又细分为:
①局部变量表(保存方法参数和局部变量的一个数组)
②操作数栈
③动态链接
④方法返回地址
⑤一些附加信息。当然这里不是我们要讲的重点!重要的是这里我们只用到其中前两个相对比较重要的局部变量表和操作数栈。需要大家对这两个结构一定了解。

分析原因!!接下来分析字节码文件中的指令(下图由Jdk自带解析工具javap解析的class文件)
在这里插入图片描述

如图我们可以看到

**int i = 0**;编译之后为:**iconst_0,istore_1**。

意思是将常量加载到了操作数栈,然后将操作数栈顶元素保存到局部变量表索引为1的变量槽中

**i = i++**;编译之后为:**ioad_1,iinc 1,1,istore_1**

这些指令指的分别是:
ioad_1:将局部变量表中的i加载到操作数栈。
iinc1,1:局部变量表中的i自增1,最后istore_1将操作数栈顶的元素再赋值给、保存到局部变量表索引为1的变量槽中。这个过程操作数栈中的值并没有改变!所以最后赋值回去的时候,局部变量表的自增1相当于被覆盖了

这个过程我们可以看出,i = i++无非就三个操作,加载入栈,表变量自增1,栈中数据重新赋值给i,相当于把在表中自增的操作给覆盖了。所以最后我们看到的结果就是i没有增加,如果这个时候我们不把结果重新存回原变量,而是存回其他变量比如j,这个时候,i就还是会保持自增1的操作。

++i也是经过三个步骤,首先局部变量表自增1,入操作数栈,出操作数栈保存到局部变量表。与i++不同的是,先自增1在进入操作数栈,那么这个时候再赋值给原变量i结果也是加1了的,如果这个时候不进行赋值保存,而是进行其他运算操作,那就是我们理解记忆的先对变量自增1,再进行运算了。

总结

i++先将表中变量i压入操作数栈进行运算,再对表中数据自增1,而++i先对表中变量自增1,再将表中变量压入操作数栈进行运算。最后就是赋值的操作了,当然也可以不赋值,单纯的i++,++i,i都会进行自增

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值