正文
一个简单的拆箱操作
javac
会自动完成拆箱的操作,我用一个名为 Main.java
的程序来演示一下。
Main.java
的内容如下
public class Main {
private int f(Integer in) {
return in;
}
}
执行如下命令对 Main.java
进行编译
javac Main.java
执行如下命令可以查看字节码文件中的内容
javap -cp . -p -v 'Main'
完整的内容较长,和 f(...)
直接相关的部分如下
private int f(java.lang.Integer);
descriptor: (Ljava/lang/Integer;)I
flags: ACC_PRIVATE
Code:
stack=1, locals=2, args_size=2
0: aload_1
1: invokevirtual #2 // Method java/lang/Integer.intValue:()I
4: ireturn
LineNumberTable:
line 3: 0
f(...)
对应的字节码指令有三条, 作用如下
-
aload_1
, 其作用是将1
号slot
中的值加载到操作数栈中(f(...)
方法只有一个参数in
,1
号slot
中保存的就是in
这个参数的引用,细节这里就不展开了) -
invokevirtual #2
, 调用常量池中与#2
对应的方法, 也就是java/lang/Integer.intValue:()I
这个方法(其实就是对in
参数调用java/lang/Integer.intValue:()I
方法) -
ireturn
, 将操作数栈栈顶的int
值作为f(...)
的返回值(操作数栈栈顶的值就是in
参数调用java/lang/Integer.intValue:()I
方法后的返回值)
显式地进行拆箱
大致可以猜到,编译器在遇到需要对 Integer
类型进行拆箱的场景时,会自动调用 Integer
类中的 intValue()
方法
我们可以写一个 Temp.java
来验证一下
public class Temp {
private int f(Integer in) {
return in.intValue();
}
}
执行如下命令就能看到 Temp.java
中的 f(...)
对应的字节码指令
javac Temp.java
javap -cp . -p -v 'Temp'
Temp.java
中的 f(...)
的字节码指令展示如下
private int f(java.lang.Integer);
descriptor: (Ljava/lang/Integer;)I
flags: ACC_PRIVATE
Code:
stack=1, locals=2, args_size=2
0: aload_1
1: invokevirtual #2 // Method java/lang/Integer.intValue:()I
4: ireturn
LineNumberTable:
line 3: 0
可见 Main.java Temp.java
中的 f(...)
在编译后生成的字节码指令确实是相同的
也可以用 cfr 这个工具验证一下。
以 cfr-0.148.jar
为例,执行如下命令,就能看到显式的拆箱操作
java -jar cfr-0.148.jar Main --sugarboxing false
运行结果如下
/*
* Decompiled with CFR 0.148.
*/
public class Main {
private int f(Integer n) {
return n.intValue();
}
}
可见,cfr
运行的结果和我们之前的猜测是一致的。
网友评论