美文网首页java 语法糖
Java 语法糖(一): 自动拆箱

Java 语法糖(一): 自动拆箱

作者: jyjz2008 | 来源:发表于2020-06-26 22:40 被阅读0次

    正文

    一个简单的拆箱操作

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

    1. aload_1, 其作用是将1slot中的值加载到操作数栈中(f(...)方法只有一个参数in1slot中保存的就是 in 这个参数的引用,细节这里就不展开了)
    2. invokevirtual #2, 调用常量池中与 #2 对应的方法, 也就是java/lang/Integer.intValue:()I 这个方法(其实就是对 in 参数调用 java/lang/Integer.intValue:()I 方法)
    3. 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 运行的结果和我们之前的猜测是一致的。

    参考文章

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

    相关文章

      网友评论

        本文标题:Java 语法糖(一): 自动拆箱

        本文链接:https://www.haomeiwen.com/subject/qkkpfktx.html