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(...)
有何不同。
对比之后,不难发现,两个函数的 access flag
是不同的(但是 入参类型 以及 返回值类型 都是完全相同的)
前往 https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.6 会看到 access flags
的描述
下面还有一段补充
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
插件,看一看字节码中对应的内容(有两张图)
图一里的红框部分相当于执行了
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
方法时,编译器会自动把 创建数组 以及 填写数组元素 的过程给补上。