正文
一个简单的装箱操作
javac 会自动完成装箱的操作,我用一个名为 Main.java 的程序来演示一下。
Main.java 的内容如下
public class Main {
private Integer f(int in) {
return in;
}
}
执行如下命令对 Main.java 进行编译
javac Main.java
执行如下命令可以查看字节码文件中的内容
javap -cp . -p -v 'Main'
完整的内容较长,和 f(...) 直接相关的部分如下
private java.lang.Integer f(int);
descriptor: (I)Ljava/lang/Integer;
flags: ACC_PRIVATE
Code:
stack=1, locals=2, args_size=2
0: iload_1
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: areturn
LineNumberTable:
line 3: 0
f(...) 对应的字节码指令有三条, 作用如下
-
iload_1, 其作用是将1号slot中的int值加载到操作数栈中(f(...)方法只有一个参数in,1号slot中保存的就是in这个参数的值) -
invokestatic #2, 调用常量池中与#2对应的静态方法, 也就是java/lang/Integer.valueOf:(I)Ljava/lang/Integer;这个方法 -
areturn, 将操作数栈栈顶的引用作为f(...)的返回值
这样分析后,可知 f(int in) 中的逻辑相当于
return Integer.valueOf(in);
那么我们可以显式地把这样的逻辑写出来,对比一下它们的字节码。我们写一个 Temp.java 来验证一下
public class Temp {
private Integer f(int in) {
return Integer.valueOf(in);
}
}
执行如下命令就能看到 Temp.java 中的 f(...) 对应的字节码指令
javac Temp.java
javap -cp . -p -v 'Temp'
Temp.java 中的 f(...) 的字节码指令展示如下
private java.lang.Integer f(int);
descriptor: (I)Ljava/lang/Integer;
flags: ACC_PRIVATE
Code:
stack=1, locals=2, args_size=2
0: iload_1
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
4: areturn
LineNumberTable:
line 3: 0
可见 Main.java 和 Temp.java 中的 f(...) 在编译后生成的字节码指令确实是相同的