是的,T…只是T[]的一个语法修饰词。
JLS 8.4.1格式参数
The last formal parameter in a list is special; it may be a variable arity parameter, indicated by an elipsis following the type.
If the last formal parameter is a variable arity parameter of type T, it is considered to define a formal parameter of type T[]. The method is then a variable arity method. Otherwise, it is a fixed arity method. Invocations of a variable arity method may contain more actual argument expressions than formal parameters. All the actual argument expressions that do not correspond to the formal parameters preceding the variable arity parameter will be evaluated and the results stored into an array that will be passed to the method invocation.
这里有一个例子来说明:
public static String ezFormat(Object... args) {
String format = new String(new char[args.length])
.replace("\0", "[ %s ]");
return String.format(format, args);
}
public static void main(String... args) {
System.out.println(ezFormat("A", "B", "C"));
// prints "[ A ][ B ][ C ]"
}
是的,上面的main方法是有效的,因为再次,String…就是String[]。此外,因为数组是协变的,字符串[]是对象[],所以你也可以用任何一种方式调用ezFormat(args)。
另请参阅
Java语言指南/变量参数
变参数陷阱#1:传递null
如何解析变参数是相当复杂的,有时它做的事情可能会让你感到惊讶。
想想这个例子:
static void count(Object... objs) {
System.out.println(objs.length);
}
count(null, null, null); // prints "3"
count(null, null); // prints "2"
count(null); // throws java.lang.NullPointerException!!!
由于varargs是如何解析的,最后一个语句调用objs = null,这当然会导致objs.length的NullPointerException。如果你想给varargs形参一个空参数,你可以做以下任何一种:
count(new Object[] { null }); // prints "1"
count((Object) null); // prints "1"
相关问题
下面是一些人们在处理变参数时问过的问题:
Bug与可变参数和重载?
如何使用可变参数和反射
最具体的方法与固定/可变的匹配(varargs)
变参数陷阱#2:添加额外参数
正如你所发现的,下面的方法是行不通的:
String[] myArgs = { "A", "B", "C" };
System.out.println(ezFormat(myArgs, "Z"));
// prints "[ [Ljava.lang.String;@13c5982 ][ Z ]"
由于可变参数的工作方式,ezFormat实际上得到2个参数,第一个是String[],第二个是String。如果您将一个数组传递给varargs,并且希望它的元素被识别为单独的参数,并且还需要添加一个额外的参数,那么您别无选择,只能创建另一个数组来容纳额外的元素。
下面是一些有用的helper方法:
static <T> T[] append(T[] arr, T lastElement) {
final int N = arr.length;
arr = java.util.Arrays.copyOf(arr, N+1);
arr[N] = lastElement;
return arr;
}
static <T> T[] prepend(T[] arr, T firstElement) {
final int N = arr.length;
arr = java.util.Arrays.copyOf(arr, N+1);
System.arraycopy(arr, 0, arr, 1, N);
arr[0] = firstElement;
return arr;
}
现在你可以做以下事情:
String[] myArgs = { "A", "B", "C" };
System.out.println(ezFormat(append(myArgs, "Z")));
// prints "[ A ][ B ][ C ][ Z ]"
System.out.println(ezFormat(prepend(myArgs, "Z")));
// prints "[ Z ][ A ][ B ][ C ]"
变参数陷阱#3:传递一个原语数组
它不“工作”:
int[] myNumbers = { 1, 2, 3 };
System.out.println(ezFormat(myNumbers));
// prints "[ [I@13c5982 ]"
可变参数只适用于引用类型。自动装箱不适用于原语数组。以下工作:
Integer[] myNumbers = { 1, 2, 3 };
System.out.println(ezFormat(myNumbers));
// prints "[ 1 ][ 2 ][ 3 ]"