Так, a T...
- це лише синтаксичний цукор для a T[]
.
Останній формальний параметр у списку є спеціальним; це може бути змінний параметр arity, позначений еліпсісом за типом.
Якщо останній формальний параметр є змінним параметром arity типу T
, вважається визначити формальний параметр типу T[]
. Тоді метод є методом змінної арності . В іншому випадку це метод фіксованої арності . Виклики методу змінної арності можуть містити більше фактичних виразів аргументів, ніж формальні параметри. Всі фактичні вирази аргументів, які не відповідають формальним параметрам, що передують параметру змінної масиву, будуть оцінені, а результати збережені в масив, який буде переданий до виклику методу.
Ось приклад для ілюстрації:
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[]
. Крім того, оскільки масиви є коваріантними, а String[]
- це Object[]
, тому ви також можете телефонувати в ezFormat(args)
будь-якому випадку.
Дивитися також
Varargs gotchas №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!!!
Через те, як розв’язуються вараги, останній оператор посилається на 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 ]"
Через те, як працюють вараги, 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 gotchas # 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 ]"