Переменное число аргументов
Иногда заранее неизвестно, сколько аргументов передадут в метод: сумма двух чисел, пяти или ни одного. Для таких случаев в Java есть varargs — параметр, принимающий любое количество значений одного типа.
Объявление varargs
После типа параметра ставят многоточие .... При вызове аргументы перечисляют через запятую — сколько угодно:
int sum(int... numbers) {
int total = 0;
for (int n : numbers) {
total += n;
}
return total;
}
void main() {
IO.println(sum(1, 2));
IO.println(sum(1, 2, 3, 4, 5));
IO.println(sum());
}Результат:
3
15
0Java сама собирает переданные значения в массив, поэтому вызывающему коду не нужно создавать его вручную.
Внутри это массив
Внутри метода параметр varargs — обычный массив. У него есть длина length и доступ по индексу:
void printInfo(String... names) {
IO.println("Количество: " + names.length);
if (names.length > 0) {
IO.println("Первый: " + names[0]);
}
}
void main() {
printInfo("Анна", "Олег", "Мария");
printInfo();
}Результат:
Количество: 3
Первый: Анна
Количество: 0Без аргументов метод получает пустой массив, а не «ничего», поэтому names.length безопасно вернёт 0.
Передача массива
Вместо списка аргументов можно передать готовый массив — Java примет его как есть:
int max(int... values) {
int best = values[0];
for (int v : values) {
if (v > best) {
best = v;
}
}
return best;
}
void main() {
int[] prices = {12, 45, 7};
IO.println(max(prices));
IO.println(max(3, 9, 4));
}Результат:
45
9Вместе с обычными параметрами
Varargs можно сочетать с обычными параметрами, но он должен стоять последним. Сначала заполняются обычные параметры, остальные аргументы попадают в массив:
void order(String customer, String... items) {
IO.println(customer + " заказывает " + items.length + " шт.: " + String.join(", ", items));
}
void main() {
order("Анна", "латте", "круассан");
}Результат:
Анна заказывает 2 шт.: латте, круассанString.join() — сам метод с varargs: он склеивает строки через разделитель.
printf
Метод System.out.printf() тоже принимает переменное число аргументов. Первым идёт шаблон, где %s обозначает место для строки, %d — для целого числа, %n — перевод строки:
void main() {
System.out.printf("%s купил %d книги%n", "Олег", 3);
}Результат:
Олег купил 3 книгиЕсли значений после шаблона меньше, чем спецификаторов, при запуске возникнет ошибка, а лишние значения просто игнорируются.
Подробнее о форматировании — в уроке о текстовых блоках и форматировании.
Частая ошибка
Varargs может быть только один и только в конце списка параметров. Иначе Java не поймёт, где заканчиваются его аргументы:
void order(String... items, String customer) {
IO.println(customer);
}
void main() {
order("латте", "Анна");
}Результат:
Main.java:1: error: varargs parameter must be the last parameter
void order(String... items, String customer) {
^
1 error
error: compilation failedПеренесите varargs в конец: order(String customer, String... items).