Иногда оказываются полезными методы, способные принимать переменное число аргументов.
Например, методу, устанавливающему соединение с Интернетом, могут понадобиться имя и пароль пользователя, имя файла, протокол и другие параметры. Если при вызове метода некоторые из этих данных опущены, то должны использоваться значения по умолчанию.
В подобных ситуациях было бы удобнее передавать только те аргументы, для которых заданные по умолчанию значения неприменимы, а для этого требуется метод, который мог бы принимать аргументы, количество которых заранее неизвестно.
До версии J2SE5 для поддержки списков аргументов переменной длины применялись два способа, ни один из которых не был особенно удобен.
Во-первых, если максимально возможное количество аргументов было невелико и заранее известно, то можно было создавать перегруженные версии метода — по одной для каждого способа его вызова. Очевидно, что такой подход применим лишь в отдельных случаях.
И во-вторых, если таких версий требовалось создавать слишком много или их максимальное количество было неопределенным, то применялся второй подход: параметры помещались в массив, а затем этот массив передавался методу.
У каждого из этих способов имеются свои недостатки, и со временем стало ясно, что для преодоления описанной проблемы следует искать другие решения.
Такое решение было предложено в JDK 5. Новое средство, которое позволило избавиться от явного формирования массива аргументов перед вызовом метода, получило название varargs (сокращение от variable-length arguments — список аргументов переменной длины).
Соответствующие методы называют методами с переменным числом аргументов (другое название — методы переменной арности). В методах этого типа список параметров имеет не фиксированную, а переменную длину, что обеспечивает дополнительную гибкость, позволяя методам принимать произвольное число аргументов.
Пользуюсь случаем, хочу спросить аудиторию: работали ли вы когда-то с WordPress-ом? Очень нужен шаблон ThemeForest Motors, уж очень сильно он подойдет для одного моего проекта. Могу отблагодарить материально.
Использование методов с переменным числом аргументов
Списки аргументов переменной длины обозначаются символом многоточия ( … ). Ниже приведен пример метода vaTest(), принимающего переменное число аргументов(в том числе и нулевое).
1 2 3 4 5 6 7 8 9 10 11 12 |
// Метод vaTest() с переменным числом аргументов // Объявление метода со списком аргументов переменной длины static void vaTest(int ... v) { System.out.println("Число аргументов: " + v.length); System.out.println("Содержимое: "); for(int i = 0; i < v.length; i++) { System.out.println(" arg " + i + ": " + v[i]); } System.out.println(); } |
Обратите внимание на синтаксис объявления параметра v:
1 |
int ... v |
Это объявление сообщает компилятору, что метод vaTest() может вызываться с указанием произвольного количества аргументов, в том числе и вовсе без них.
Более того, оно означает неявное объявления аргумента v как массива типа int[]. Таким образом, в теле метода vaTest() доступ к параметру v осуществляется с помощью обычного синтаксиса обращения к массивам.
Ниже приведен полный исходный код примера программы, которая демонстрирует использование метода vaTest().
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
// Демонстрация использования метода с переменным числом аргументов class VarArgs { // Метод vaTest() допускает переменное число аргументов static void vaTest(int ... v) { System.out.println("Число аргументов: " + v.length); System.out.println("Содержимое: "); for(int i = 0; i < v.length; i++) { System.out.println(" arg " + i + ": " + v[i]); } System.out.println(); } public static void main(String args[]) { // Метод vaTest() может вызываться с // переменным числом аргументов vaTest(1); // 1 аргумент vaTest(1, 2, 3); // 3 аргумента vaTest(); // без аргументов } } |
Выполнение этой программы дает следующий результат.
1 2 3 4 5 6 7 8 9 10 11 12 |
Количество аргументов: 1 Содержимое: arg 0: 10 Количество аргументов: 1 Содержимое: arg 0: 1 arg 1: 2 arg 2: 3 Количество аргументов: 0 Содержимое: |
В приведенной выше программе обращает на себя внимание следующее.
Во-первых, как пояснялось выше, обращение к параметру v в методе vaTest() осуществляется как к массиву. Дело в том, что он действительно является массивом (и, таким образом, может иметь переменную длину).
Многоточие в объявлении этого метода указывает компилятору на использование переменного числа аргументов, а также на необходимость поместить их в массив v.
Во-вторых, в методе main() присутствуют вызовы метода vaTest() с использованием различного числа аргументов, в том числе и без указания аргумента. Указываемые аргументы автоматически помещаются в массив v. Если же аргументы не указаны, длина этого массива будет равна нулю.
Помимо списка параметров переменной длины, в объявлении метода могут указываться и обычные параметры, но при одном условии: массив параметров переменной длины должен быть указан последним. Например, приведенное ниже объявление метода является вполне допустимым.
1 2 3 |
int doIt(int a, int b, doublce c, int ... vals) { // тело метода } |
В этом случае первым трем аргументам, указанным при вызове метода doIt(), будут соответствовать первые три параметра в объявлении метода, тогда как остальные аргументы будут приниматься из массива vals.
Ниже приведен переработанный вариант метода vaTest(), в котором метод получает как обычные аргументы, так и массив аргументов переменной длины.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// Использование массива аргументов переменной длины // наряду с обычными аргументами class VarArgs2 { // Здесь msg - обычный параметр, // а аргумент v - массив параметров переменной длины // Обычный параметр и параметр в виде массива переменной длины static void vaTest(String msg, int ... v) { System.out.println(msg + v.length); System.out.println("Содержимое: "); for(int i = 0; i < v.length; i++) { System.out.println(" arg " + i + ": " + v[i]); } System.out.println(); } public static void main(String args[]) { vaTest("Один аргумент в массиве: ", 10); vaTest("Три аргумента в массиве: ", 1, 2, 3); vaTest("Отсутствуют аргументы в виде массива: "); } } |
Выполнение этого фрагмента кода дает следующий результат.
1 2 3 4 5 6 7 8 9 10 11 12 |
Один аргумент в массиве: 1 Содержимое: arg 0: 10 Три аргумента в массиве: 3 Содержимое: arg 0: 1 arg 1: 2 arg 2: 3 Отсутствуют аргументы в массиве: 0 Содержимое: |
Помните о том, что список параметров переменной длины должен указываться последним. Например, следующее объявление метода недопустимо.
1 2 3 |
int doIt(int a, int b, double c, int ... vals, boolean stopFlag) { // Ошибка!!! } |
В данном примере сделана попытка указать обычный параметр после списка параметров переменной длины.
Существует еще одно ограничение, которое следует соблюдать: список параметров переменной длины можно указать в методе только один раз. Например, приведенное ниже объявление метода недопустимо.
1 2 3 |
int doIt(int a, int b, double c, int ... vals, double ... morevals) { // Ошибка } |
Ошибкой в данном случае является попытка указать два разных списка параметров переменной длины.