JVM中i++和++i

问:如下java代码,最后a、b的值分别是多少?

public class Demo3_2 {
 
    public static void main(String[] args) {
        int a=10;
        int b = a++ +  ++a  + a--;
        System.out.println(a);//?
        System.out.println(b);//?
    }
}

一些有经验的开发人员,可能立马就能得出答案:   a最后的值为11 ,b最后的值为34 , 那么为什么结果是这样呢?

本篇,笔者试图从jvm指令的层面来进行分析。

首先,我们用javap 命令反编译这段源码:

javap  -v Demo3_2.class ,发现其中main方法生成的字节码指令如下:

public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=3, args_size=1
         0: bipush        10
         2: istore_1
         3: iload_1
         4: iinc          1, 1
         7: iinc          1, 1
        10: iload_1
        11: iadd
        12: iload_1
        13: iinc          1, -1
        16: iadd
        17: istore_2
        18: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        21: iload_1
        22: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
        25: getstatic     #2                  // Field java/lang/System.out:Ljava/io/PrintStream;
        28: iload_2
        29: invokevirtual #3                  // Method java/io/PrintStream.println:(I)V
        32: return
      LineNumberTable:
        line 32: 0
        line 33: 3
        line 34: 18
        line 35: 25
        line 36: 32
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      33     0  args   [Ljava/lang/String;
            3      30     1     a   I
           18      15     2     b   I

 

 

我们来分析下,这段字节码指令:

stack=2 表示栈桢中操作数栈的最大深度为2,locals=3表示局部变量表有3个槽位。槽位0是args ,也就是main方法的入参,槽位1和2分别对应局部变量a和b

 

bipush 10  执行引擎读取到该指令,将数字10压入操作数栈

istore_1    执行引擎将操作数栈中的值弹出,放入到局部变量表1号槽位,此时1号槽位的值为10

iload_1     执行引擎将局部变量表1号槽位的值压入操作数栈,此时操作数栈中存放的第一个值为10

iinc 1,1     执行引擎将局部变量表1号槽位变量值加1,此时1号槽位的值变为11

iinc 1,1     执行引擎将局部变量表1号槽位变量值加1,此时1号槽位的值变为12

iload_1     执行引擎将局部变量表1号槽位的值压入操作数栈,此时操作数栈中存放的第二个值为12

iadd         执行引擎执行将操作数栈的两个数字相加得到22【10+12】,此时操作数栈中只留下一个值22

iload_1     执行引擎将局部变量表1号槽位的值压入操作数栈,此时操作数栈中存放的第二个值为12

iinc 1,-1   执行引擎将局部变量表1号槽位变量值减1,此时1号槽位的值变为11

iadd         执行引擎将操作数栈的两个数字相加得到34【22+12】,此时操作数栈中只留下一个值34

istore_2   执行引擎将操作数栈中值弹出,放入局部变量表2号槽位,此时2号槽位的值为34

......

 

因此,最终的结果是:a的值为11,b的值为34

 

最后我们可以得出结论,i++和++i 的不同是在于字节码中:

i++ :   先执行iload (将局部变量表slot中的变量压入操作数栈) ,再执行iinc 1,1(局部变量表slot槽中变量自加1)

++i :   先执行iinc 1,1(局部变量表slot槽中变量自加1) ,再执行iload (将局部变量表slot中的变量压入操作数栈) 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值