Java 语法糖(二): 自动装箱

正文

一个简单的装箱操作

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(...) 对应的字节码指令有三条, 作用如下

  1. iload_1, 其作用是将1slot中的int值加载到操作数栈中(f(...)方法只有一个参数in1slot中保存的就是 in 这个参数的值)
  2. invokestatic #2, 调用常量池中与 #2 对应的静态方法, 也就是 java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 这个方法
  3. 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.javaTemp.java 中的 f(...) 在编译后生成的字节码指令确实是相同的

参考文章

  1. https://www.benf.org/other/cfr/boxing-isnt-magic.html

你可能感兴趣的:(Java 语法糖(二): 自动装箱)