从jvm字节码指令层面,彻底掌握a++跟++a的区别

文章通过一个具体的例子解释了Java中自增运算符的用法,详细分析了JVM执行字节码的过程,揭示了运算顺序和变量状态的变化。在给定的示例中,由于运算符的优先级,最终结果是c=5,a=3。文章强调了解运算符的工作原理对于正确理解和处理复杂运算至关重要。
摘要由CSDN通过智能技术生成

1.问题:遇到复杂运算,怎么办

如果只知道表面理解a++与++a的区别:a++,先使用,再赋值;++a,先自增,再使用。那么遇到复杂的运算就会迷糊了,比如

        //第1题
        int a = 1;
        int c = a + ++a + a++;
        System.out.printf("c="+c+",a="+a);//c等于5,a等于3

 

2.为什么输出结果是c=5,a=3呢?分析过程如下:

可能很多人都知道a=3,因为进行了2次自增,那c呢?其实答案都在字节码指令中,如下:

我们都知道jvm分为堆、方法区、虚拟机栈、本地方法栈,程序计数器,而是jvm在运行具体的方法时,会在虚拟机栈中创建对应的栈帧,栈帧中有局部变量表(存放基本类型变量,下面简称变量表)操作数栈(用来存放计算的操作数以及返回结果,下面简称栈)、方法出口,动态链接。

那我们就开始分析字节码指令运行的过程:

 0 iconst_1  :将常量1压入栈顶,栈中元素为1
 1 istore_1   :将栈顶int类型的值,赋给变量表的第二个位置的变量,此时a = 1
 2 iload_1     :   将变量表的第二个位置的变量的值,压入栈,即把a的值压入栈顶,栈元素为1
 3 iinc 1 by 1:把变量表中的第二个位置的变量+1,与栈无关,即a已经等于2
 6 iload_1     :   把变量表中的第二位置的变量压入栈1,即把2压入栈顶,此时栈元素为2,1
 7 iadd          :从栈顶弹出两个int类型的值,进行相加,再将结果压入栈,此时栈元素为3
 8 iload_1     :将变量表中第二个位置的变量压入栈,即a=2压入栈,此时栈元素为2,3
 9 iinc 1 by 1 :将变量表中第二个位置的变量+1,即a=3
12 iadd         :  从栈顶弹出两个int类型的值,进行相加,再将结果压入栈,此时栈元素为5
13 istore_2   :  将栈顶int类型的值,赋给变量表的第三个位置的变量,即把5赋值给变量c

 所以结果打印出来c=5,a=3。

3.总结

c= a + ++a + a++,  因为计算机是从左到右计算,从入栈角度,将等号右边式子分成三个主步骤(从+、-、*、/算术符号开始分割):

        第一,将第一个a存入栈,此时a=1,栈元素为1

        第二,因为++优先级高于+算术运算符,++a,即压栈前a先加1,此时a=2了,把2压入栈,此时栈元素为2、1,进行+,则栈元素为3

        第三,a++,先将第三个a压入栈,此时a=2,栈元素为2,3,出栈计算2+3=5,并赋值给c,c=5,另外a自增,变成3。

        简单技巧:无论多复杂的运算,如果是++a,后面的a就进行加1,如果是a++,就不变。上面例子中第二个a进行++a,即1+1 =2 ,所以第三个a已经变成了2,c=1+2+2=5,这种方法能简单又正确地计算

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值