Когда вы используете Varargs в Java? - PullRequest
189 голосов
/ 20 апреля 2009

Я боюсь varargs. Я не знаю, для чего их использовать.

Кроме того, опасно позволять людям передавать столько аргументов, сколько они хотят.

Какой пример контекста, который будет хорошим местом для их использования?

Ответы [ 8 ]

149 голосов
/ 20 апреля 2009

Varargs полезны для любого метода, который должен иметь дело с неопределенным числом объектов . Один хороший пример - String.format. Строка формата может принимать любое количество параметров, поэтому вам необходим механизм для передачи любого количества объектов.

String.format("This is an integer: %d", myInt);
String.format("This is an integer: %d and a string: %s", myInt, myString);
78 голосов
/ 20 апреля 2009

Хорошее эмпирическое правило будет:

"Использовать varargs для любого метода (или конструктора), для которого требуется массив T (независимо от типа T) в качестве входных данных".

Это облегчит вызовы этих методов (не нужно делать new T[]{...}).

Вы можете расширить это правило, чтобы включить методы с аргументом List<T>, при условии, что этот аргумент предназначен только для ввода (т. Е. Список не изменяется методом).

Кроме того, я бы воздержался от использования f(Object... args), потому что это ускользает от программирования с неясными API.

В терминах примеров я использовал его в DesignGridLayout , где я могу добавить несколько JComponent s за один вызов:

layout.row().grid(new JLabel("Label")).add(field1, field2, field3);

В приведенном выше коде метод add () определяется как add(JComponent... components).

Наконец, реализация таких методов должна учитывать тот факт, что он может быть вызван с пустым vararg! Если вы хотите навязать хотя бы один аргумент, вы должны использовать такой уродливый трюк, как:

void f(T arg1, T... args) {...}

Я считаю этот трюк уродливым, потому что реализация метода будет менее простой, чем просто наличие T... args в списке аргументов.

Надеюсь, это поможет прояснить вопрос о varargs.

34 голосов
/ 02 января 2012

Я часто использую varargs для вывода в журналы в целях отладки.

Практически каждый класс в моем приложении имеет метод debugPrint ():

private void debugPrint(Object... msg) {
    for (Object item : msg) System.out.print(item);
    System.out.println();
}

Затем, внутри методов класса, у меня есть вызовы, подобные следующим:

debugPrint("for assignment ", hwId, ", student ", studentId, ", question ",
    serialNo, ", the grade is ", grade);

Когда я убедился, что мой код работает, я закомментировал код в методе debugPrint (), чтобы журналы не содержали слишком много посторонней и нежелательной информации, но я могу оставить отдельные вызовы для debugPrint () раскомментирована. Позже, если я обнаружу ошибку, я просто раскомментирую код debugPrint (), и все мои вызовы debugPrint () будут повторно активированы.

Конечно, я мог бы так же легко отказаться от varargs и вместо этого сделать следующее:

private void debugPrint(String msg) {
    System.out.println(msg);
}

debugPrint("for assignment " + hwId + ", student " + studentId + ", question "
    + serialNo + ", the grade is " + grade);

Однако в этом случае, когда я закомментирую код debugPrint (), серверу все еще приходится сталкиваться с проблемой объединения всех переменных при каждом вызове debugPrint (), даже если с результирующей строкой ничего не делается , Однако, если я использую varargs, сервер должен только поместить их в массив, прежде чем он поймет, что он им не нужен. Много времени сохранено.

12 голосов
/ 25 сентября 2012

Varargs можно использовать, когда мы не уверены в количестве аргументов, передаваемых в методе. Он создает массив параметров неопределенной длины в фоновом режиме, и такой параметр можно рассматривать как массив во время выполнения.

Если у нас есть метод, который перегружен для приема разного количества параметров, то вместо перегрузки метода разное время мы можем просто использовать концепцию varargs.

Также, когда тип параметров будет меняться, использование «Object ... test» значительно упростит код.

Например:

public int calculate(int...list) {
    int sum = 0;
    for (int item : list) {
        sum += item;
    }
    return sum;
}

Здесь косвенно массив типа int (list) передается как параметр и обрабатывается как массив в коде.

Для лучшего понимания перейдите по этой ссылке (она мне очень помогла в понимании этой концепции): http://www.javadb.com/using-varargs-in-java

П.С .: Даже я боялся использовать варагс, когда не знал об этом. Но сейчас я к этому привык. Как говорится: «Мы цепляемся за известное, боимся неизвестного», так что просто используйте его столько, сколько сможете, и он вам тоже понравится :)

11 голосов
/ 13 октября 2014

Varargs - это функция, добавленная в Java версии 1.5.

Зачем это использовать?

  1. Что если, вы не знаете, сколько аргументов нужно передать для метода?
  2. Что если, вы хотите передать методу неограниченное количество аргументов?

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

Создает массив с заданными аргументами и передает массив методу.

Пример:

public class Solution {



    public static void main(String[] args) {
        add(5,7);
        add(5,7,9);
    }

    public static void add(int... s){
        System.out.println(s.length);
        int sum=0;
        for(int num:s)
            sum=sum+num;
        System.out.println("sum is "+sum );
    }

}

Выход:

2

сумма 12

3

сумма 21

5 голосов
/ 21 апреля 2009

У меня тоже страх, связанный с варагсами:

Если вызывающая программа передаст методу явный массив (в отличие от нескольких параметров), вы получите общую ссылку на этот массив.

Если вам нужно сохранить этот массив внутри, вы можете сначала его клонировать, чтобы вызывающая сторона не смогла изменить его позже.

 Object[] args = new Object[] { 1, 2, 3} ;

 varArgMethod(args);  // not varArgMethod(1,2,3);

 args[2] = "something else";  // this could have unexpected side-effects

Хотя в действительности это не отличается от передачи любого типа объекта, состояние которого может измениться позже, поскольку массив обычно (в случае вызова с несколькими аргументами вместо массива) является свежим, созданным компилятором внутри, что Вы можете безопасно использовать, это, безусловно, неожиданное поведение.

1 голос
/ 04 августа 2016

В Java-документе Var-Args совершенно очевидно использование var args:

http://docs.oracle.com/javase/1.5.0/docs/guide/language/varargs.html

об использовании говорит:

"Так когда же тебе следует использовать варагс? Как клиент, вы должны пользоваться ими всякий раз, когда API предлагает их. Важные области применения в основных API-интерфейсах включают отражение, форматирование сообщений и новую функцию printf. Как разработчик API, вы должны использовать их экономно, только когда выгода действительно убедительна. Вообще говоря, вам не следует перегружать метод varargs, иначе программистам будет сложно определить, какая перегрузка вызывается. «

1 голос
/ 20 апреля 2009

Я часто использую varargs для конструкторов, которые могут использовать какой-либо объект фильтра. Например, большая часть нашей системы, основанная на Hadoop, основана на Mapper, который обрабатывает сериализацию и десериализацию элементов в JSON и применяет несколько процессоров, каждый из которых принимает элемент содержимого и либо изменяет и возвращает его, либо возвращает нуль отклонить.

...