专栏原创出处:github-源笔记文件 (opens new window) ,github-源码 (opens new window),欢迎 Star,转载请附上原文出处链接和本声明。
Java 核心知识专栏系列笔记,系统性学习可访问个人复盘笔记-技术博客 Java 核心知识 (opens new window)
# 一、可变长参数的定义
使用 类型... 名称
定义为可变长参数(Varargs),一个方法只能有一个可变长参数并且必须是方法最后一个参数。
void method(String... args) // 可变长参数
void method(String first, String... args) // args 为可变长参数
void method(String... args, String s) // 编译不通过
从本质上理解,我们可以把可变长参数当成一个语法糖,最终它是由数组表示的。 可变长参数可以看做是一个不需要显示的创建数组就能使用的「数组」,创建数组由虚拟机编译时自动完成。
# 二、可变长参数特性
- 可变长参数底层使用数组实现
[Ljava/lang/String; 表示是一个字符串数组([
表示数组,L
表示引用类型)。
public static void method(java.lang.String, java.lang.String...);
编译后描述符 : (Ljava/lang/String;[Ljava/lang/String;)V
- 不指定可变长参数时,默认会创建一个长度为 0 的空数组传入
public class A {
public static void method(String... args) {}
public static void main(String[] args) {
A.method();
}
Code:
stack=1, locals=1, args_size=1
0: iconst_0 // 将 0 压入栈顶 (数组长度为 0)
1: anewarray #2 // 创建一个引用类型为 String 的数组并将其引用值压入栈顶
4: invokestatic #3 // 调用 method(String... args) 方法,将数组传入
7: return
}
- 能够和固定参数的方法匹配,也能够与可变长参数的方法匹配,则选择固定参数的方法
public class A {
public static void method(String first, String second) {
System.out.println("first,second");
}
public static void method(String first, String... args) {
System.out.println("first,args");
}
public static void main(String[] args) {
A.method("a", "b"); // first,second
}
}
- 重写可变长参数的方法时,最好子方法也用可变长参数表示
static class Base {
void print(String... args) {
System.out.println("Base");
}
}
static class Sub extends Base { // 子类,覆写父类方法
@Override void print(String[] args) {
System.out.println("Sub");
}
}
// 静态类型为 Base,直接查找 Base 的 print 方法
Base base = new Sub();
base.print("hello");
// 静态类型为 Sub,直接查找 Sub 的 print 方法,因为是数组格式,编译不通过
Sub sub = new Sub();
sub.print("hello"); // 编译不通过
对于重载重写及编译期间的静态分派参考 从方法调用的角度分析重载、重写的本质 (opens new window)
# 三、应用场景
参数具体个数未知,使用可变长参数
使用集合代替不确定长度的数组时,考虑性能情况,使用可变长参数代替集合
提供更快捷方便的 API,比如 LOG
public void info(String format, Object... arguments);
# 总结
可变长参数底层是数组,一个方法只能有一个可变长参数并且是方法参数的最后一个位置
可变长参数如果没有传入任何值,默认会传入一个空数组
能够和固定参数的方法匹配,也能够与可变长参数的方法匹配,则选择固定参数的方法
重写可变长参数的方法时,最好子方法也用可变长参数表示(用数组表示可能会有编译问题)