Java可变参数是编译器语法糖,底层转为数组传递;声明用类型...参数名,必须位于参数列表末尾且唯一;调用时自动转为数组,运行时即普通数组,重载时优先匹配非varargs方法。

Java 的可变参数(varargs)表面上看是“任意个参数”,实际是编译器做的语法糖,底层统一转为数组传递。
语法写法与调用规则
方法声明时用 类型... 参数名(注意三个点是连续的,不能有空格),例如:
public void print(String... messages) { ... }
调用时可以传 0 个、1 个或多个对应类型的参数:
立即学习“Java免费学习笔记(深入)”;
- print(); → 空数组 new String[0]
- print("hello"); → 单元素数组 new String[]{"hello"}
- print("a", "b", "c"); → 三元素数组 new String[]{"a","b","c"}
varargs 必须是方法参数列表的最后一个,且一个方法最多只能有一个 varargs 参数。
编译期转换:语法糖的本质
javac 编译时会把 varargs 调用自动改写为显式数组创建。比如:
print("x", "y");
等价于编译后生成的字节码调用:
print(new String[]{"x", "y"});
反编译 class 文件可见,方法签名中 varargs 参数实际就是普通数组类型(如 String[]),JVM 完全不知 varargs 概念——它只认数组。
运行时表现:就是普通数组
在方法体内,varargs 形参可直接当数组使用:
- 获取长度:messages.length
- 遍历:for (String s : messages)
- 索引访问:messages[0]
也可以传入已有的数组,但需显式强制转型(否则编译报错):
String[] arr = {"p", "q"};
print(arr); // ✅ 合法
print((String...) arr); // ✅ 显式转型,效果同上
重载与歧义:优先匹配非 varargs 方法
当存在多个重载方法时,编译器优先选择参数个数和类型完全匹配的非 varargs 版本。例如:
void foo(String s) { ... }
void foo(String... s) { ... }
调用 foo("test") 会绑定到第一个方法,而非第二个。只有当没有精确匹配时,才启用 varargs 版本。
若两个 varargs 方法产生歧义(如 foo(Object...) 和 foo(String...) 同时存在且传 null),编译失败。










