如下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);//?
}
}
我们用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中的变量压入操作数栈)


阅读排行


Copyright © 叮叮声的奶酪 版权所有
备案号:鄂ICP备17018671号-1