Java 语法糖(四): Varargs (变长参数)

正文

java 支持变长参数, 那么这个功能是如何实现的呢?
先写段简单的程序尝试一下

package com.fake;

public class VarArgsTest {

    public static void main(String... args) {
        System.out.println(args.getClass());
    }
}

运行结果如下图所示


运行结果.png

名为 args 的参数的类型看起来就是 String[]

那么我们在 VarArgsTest 类中写两个函数试一试 varargs 和普通的数组参数有何不同(新的代码如下)。

package com.fake;

public class VarArgsTest {
    private void f1(int... args) {

    }

    private void f2(int[] args) {

    }

    public static void main(String[] args) {
        new VarArgsTest().f1(999, 888, 777);
        new VarArgsTest().f2(new int[]{999, 888, 777});
    }
}

build 之后,在 IntelliJ IDEA 里借助 Bytecode viewer 插件看一看 f1(...)f2(...) 有何不同。

圖片.png

对比之后,不难发现,两个函数的 access flag 是不同的(但是 入参类型 以及 返回值类型 都是完全相同的)

圖片.png

前往 https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6 会看到 access flags 的描述

圖片.png

下面还有一段补充

The ACC_VARARGS flag indicates that this method takes a variable number of arguments at the source code level. A method declared to take a variable number of arguments must be compiled with the ACC_VARARGS flag set to 1. All other methods must be compiled with the ACC_VARARGS flag set to 0.

那么当我们调用 varargs 方法时,编译器会帮我们把参数转化为数组吗?
实践出真知,我们来试一试。
我在刚才的 VarArgsTest 类中写了一个 main 方法

public static void main(String[] args) {
    new VarArgsTest().f1(999, 888, 777);
    new VarArgsTest().f2(new int[]{999, 888, 777});
}

继续借助 Bytecode viewer 插件,看一看字节码中对应的内容(有两张图)

图一.png

图一里的红框部分相当于执行了

f1(new int[]{999, 888, 777})
图二.png

图二里的红框部分相当于执行了

f2(new int[]{999, 888, 777})

这么一对比,就会发现,编译器会帮忙把
new VarArgsTest().f1(999, 888, 777); 转化为
new VarArgsTest().f1(new int[]{999, 888, 777});

由此可以推测,在调用 varargs 方法时,编译器会自动把 创建数组 以及 填写数组元素 的过程给补上。

参考文章

  1. https://www.benf.org/other/cfr/varargs.html
  2. https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容