Да, это T...
только синтаксический сахар для T[]
.
Последний формальный параметр в списке является специальным; это может быть переменный параметр арности , обозначаемый elipsis после типа.
Если последний формальный параметр является переменным параметром arity типа T
, считается, что он определяет формальный параметр типа T[]
. Метод тогда является методом переменной арности . В противном случае это метод фиксированной арности . Вызовы метода переменной арности могут содержать больше фактических выражений аргументов, чем формальных параметров. Все фактические выражения аргументов, которые не соответствуют формальным параметрам, предшествующим параметру переменной arity, будут оценены, а результаты сохранены в массив, который будет передан в вызов метода.
Вот пример для иллюстрации:
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[]
. Кроме того, поскольку массивы являются ковариантными, a String[]
- это a Object[]
, поэтому вы также можете вызывать в ezFormat(args)
любом случае.
Смотрите также
Varargs Gotchas # 1: прохождение null
Как решить varargs довольно сложно, и иногда это делает вещи, которые могут вас удивить.
Рассмотрим этот пример:
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
, что, конечно, вызвало бы NullPointerException
с objs.length
. Если вы хотите дать один null
аргумент параметру varargs, вы можете сделать одно из следующих:
count(new Object[] { null }); // prints "1"
count((Object) null); // prints "1"
Смежные вопросы
Ниже приведен пример некоторых вопросов, которые люди задавали при работе с varargs:
Vararg Gotchas # 2: добавление дополнительных аргументов
Как вы узнали, следующее не «работает»:
String[] myArgs = { "A", "B", "C" };
System.out.println(ezFormat(myArgs, "Z"));
// prints "[ [Ljava.lang.String;@13c5982 ][ Z ]"
Из-за того, как работает varargs, ezFormat
фактически получает 2 аргумента, первый - a String[]
, второй - a String
. Если вы передаете массив в varargs и хотите, чтобы его элементы распознавались как отдельные аргументы, и вам также необходимо добавить дополнительный аргумент, у вас нет другого выбора, кроме как создать другой массив, который будет содержать дополнительный элемент.
Вот несколько полезных вспомогательных методов:
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 ]"
Varargs получил # 3: передавая массив примитивов
Это не "работает":
int[] myNumbers = { 1, 2, 3 };
System.out.println(ezFormat(myNumbers));
// prints "[ [I@13c5982 ]"
Varargs работает только со ссылочными типами. Автобокс не применяется к массиву примитивов. Следующие работы:
Integer[] myNumbers = { 1, 2, 3 };
System.out.println(ezFormat(myNumbers));
// prints "[ 1 ][ 2 ][ 3 ]"