ПрограммированиеJava разработчик

Что такое varargs (аргументы переменной длины) в Java, как они работают и какие подводные камни существуют при их использовании?

Проходите собеседования с ИИ помощником Hintsage

Ответ

Varargs — это синтаксис, позволяющий методу получать переменное количество аргументов одного типа. Объявляются с помощью троеточия:

public void printNames(String... names) { for (String name : names) { System.out.println(name); } }

Как это работает?

Varargs параметр внутри метода просто — это массив соответствующего типа: String[] names в примере выше. Можно вызывать метод с любым количеством аргументов или с массивом:

printNames("Igor", "Anna", "Maria"); printNames(new String[] {"Alex", "Inna"});

Тонкости использования:

  • Varargs должен быть последним параметром в списке параметров метода.
  • В одном методе разрешён только один varargs параметр.
  • Возможно неоднозначности вызова, если есть перегрузка между массивом и varargs, а также между разными типами varargs.
  • При передаче null в varargs — метод получит null, а не пустой массив!

Вопрос с подвохом

Вопрос: Какую длину будет иметь массив varargs параметра, если вы вызовете метод без передачи аргументов?

Ответ: В этом случае переменная varargs будет ссылкой на массив нулевой длины: new String[0]. Не будет null!

public void foo(Integer... args) { System.out.println(args.length); } // foo(); // Выведет: 0

Примеры реальных ошибок из-за незнания тонкостей темы


История

В библиотеке логирования был метод log(String... messages). При вызове log(null) возникал NullPointerException внутри метода (ожидали, что messages — пустой массив, вместо этого был null). Для решения пришлось явно проверять на null.


История

Разработчик создал перегрузку:

public void doSomething(String[] arr) {...} public void doSomething(String... arr) {...}

При передаче массива, вызвался не тот метод, который ожидался, что привело к потере части данных. Различие между массивом и varargs оказалось неочевидным.


История

В проекте добавили второй параметр после varargs:

public void foo(String... args, int count) {...} // Ошибка компиляции!

Это привело к ошибке и срыву сборки, потому что varargs должен быть последним.