Java, 3 точки в параметрах

822

Что означают 3 точки в следующем методе?

public void myMethod(String... strings){
    // method body
}
Викрам
источник

Ответы:

988

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

См. Раздел «Произвольное количество аргументов» здесь: http://java.sun.com/docs/books/tutorial/java/javaOO/arguments.html#varargs

В вашем примере вы можете назвать это как-либо из следующего:

myMethod(); // Likely useless, but possible
myMethod("one", "two", "three");
myMethod("solo");
myMethod(new String[]{"a", "b", "c"});

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

Важное примечание 2: аргумент, который получает значение, ...должен быть последним в сигнатуре метода. Итак, myMethod(int i, String... strings)все в порядке, но myMethod(String... strings, int i)не в порядке.

Спасибо Vash за разъяснения в своем комментарии.

Kiswa
источник
112
Вы ошибаетесь, в этом «один или несколько», с помощью varargs мы можем указать 0 или более, и это всегда должно быть последним параметром в методе. Метод x (String ... params) может быть вызван как x (), или метод y (String pram, String ... params) может быть вызван как y ("1")
Дамиан Лещинский - Ваш
2
Я бы хотел, чтобы это тоже сработало. myMethod ("one", "two", "three", new String [] {"a", "b", "c" "});
2sb
2
Почему вам разрешено давать методу 0 параметров? Это, скорее всего, приведет к ArrayIndexOutOfBoundsException. Теперь вы всегда должны принимать это во внимание.
Olle Söderström
11
Потому что они необязательны. Это зависит от разработчика, который решил использовать необязательные аргументы для правильной реализации метода, чтобы иметь ноль или более из них.
Kiswa
@ OlleSöderström Другая причина заключается в том, что формальный параметр преобразуется в массив во время компиляции. Это означает, что передача в массиве дает тот же результат. Поскольку длина массива не известна во время компиляции, ограничение на прохождение хотя бы одного элемента можно обойти простым вызовом someMethod(new SomeType[] { }). Это было бы взломом, не так ли?
MC Emperor
124

Эта функция называется varargs , и она появилась в Java 5. Она означает, что функция может получать несколько Stringаргументов:

myMethod("foo", "bar");
myMethod("foo", "bar", "baz");
myMethod(new String[]{"foo", "var", "baz"}); // you can even pass an array

Затем вы можете использовать Stringvar в качестве массива:

public void myMethod(String... strings){
    for(String whatever : strings){
        // do what ever you want
    }

    // the code above is is equivalent to
    for( int i = 0; i < strings.length; i++){
        // classical for. In this case you use strings[i]
    }
}

Этот ответ в значительной степени заимствован у Кишвы и Лоренцо ... а также из комментария Графена.

Cristian
источник
13
Когда код попадает в байт - код, он является массивом. Все остальное синтаксис поддерживается только компилятором.
Донал Феллоуз
Этот ответ в значительной степени заимствует у Кишвы и Лоренцо, если я правильно читаю правки.
Мэтт Митчелл
3
@ Граф 'лучше отредактировать свой ответ и сделать его более правильным, чем оставить его в покое. И если другой ответ является источником вашего улучшения, значит, так и есть. По крайней мере, он честен в этом (и я предполагаю, что он проголосовал за другие ответы, которые помогли ему ... правильно?).
1
@ Будет ли он честен после того, как я это укажу, и это достаточно хорошо. Спасибо за поиск.
Мэтт Митчелл
23

Это Вараргс :)

Varargs, короткий для аргументов переменной длины, является функцией, которая позволяет методу принимать переменное количество аргументов (ноль или более). С помощью varargs стало проще создавать методы, которые должны принимать переменное число аргументов. Функция переменного аргумента была добавлена ​​в Java 5.

Синтаксис varargs

Vararg обозначается тремя многоточиями (три точки) после типа данных, его общая форма

return_type method_name(data_type ... variableName){
}  

Потребность в варагс

До Java 5, в случае необходимости переменного количества аргументов, было два способа справиться с этим

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

Преимущества varargs

Предлагает гораздо более простой вариант. Меньше кода, так как нет необходимости писать перегруженные методы.

Пример varargs

public class VarargsExample {
 public void displayData(String ... values){
  System.out.println("Number of arguments passed " + values.length);
  for(String s : values){
   System.out.println(s + " ");
  }
 }

 public static void main(String[] args) {
  VarargsExample vObj = new VarargsExample();
  // four args
  vObj.displayData("var", "args", "are", "passed");
  //three args
  vObj.displayData("Three", "args", "passed");
  // no-arg
  vObj.displayData();
 }
}
Output

Number of arguments passed 4
var 
args 
are 
passed 
Number of arguments passed 3
Three 
args 
passed 
Number of arguments passed 0

Из программы видно, что длина используется здесь для определения количества аргументов, переданных методу. Это возможно, потому что varargs неявно передаются в виде массива. Независимо от того, какие аргументы передаются как varargs, они хранятся в массиве, на который ссылается имя, данное varargs. В этой программе имя массива есть значения. Также обратите внимание, что метод вызывается с другим количеством аргументов, сначала вызывается с четырьмя аргументами, затем с тремя аргументами, а затем с нулевыми аргументами. Все эти вызовы обрабатываются одним и тем же методом, который принимает varargs.

Ограничение с помощью varargs

В методе могут быть другие параметры с параметром varargs, однако в этом случае параметр varargs должен быть последним параметром, объявленным методом.

void displayValues(int a, int b, int  values) // OK
   void displayValues(int a, int b, int  values, int c) // compiler error

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

void displayValues(int a, int b, int  values, int  moreValues) // Compiler error

Перегрузка varargs Методы

Возможно перегрузить метод, который принимает параметр varargs. Метод Varargs может быть перегружен -

Типы его параметра vararg могут быть разными. Добавляя другие параметры. Пример перегрузки метода varargs

public class OverloadingVarargsExp {
 // Method which has string vararg parameter
 public void displayData(String ... values){
  System.out.println("Number of arguments passed " + values.length);
  for(String s : values){
   System.out.println(s + " ");
  }
 }

 // Method which has int vararg parameter
 public void displayData(int ... values){
  System.out.println("Number of arguments passed " + values.length);
  for(int i : values){
   System.out.println(i + " ");
  }
 }

 // Method with int vararg and one more string parameter
 public void displayData(String a, int ... values){
  System.out.println(" a " + a);
  System.out.println("Number of arguments passed " + values.length);
  for(int i : values){
   System.out.println(i + " ");
  }
 }

 public static void main(String[] args) {
  OverloadingVarargsExp vObj = new OverloadingVarargsExp();
  // four string args
  vObj.displayData("var", "args", "are", "passed");

  // two int args
  vObj.displayData(10, 20);

  // One String param and two int args
  vObj.displayData("Test", 20, 30);
 }
}
Output

Number of arguments passed 4
var 
args 
are 
passed 

Number of arguments passed 2
10 
20

 a Test
Number of arguments passed 2
20 
30 

Varargs и перегрузки двусмысленность

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

public class OverloadingVarargsExp {
 // Method which has string vararg parameter
 public void displayData(String ... values){
  System.out.println("Number of arguments passed " + values.length);
  for(String s : values){
   System.out.println(s + " ");
  }
 }

 // Method which has int vararg parameter
 public void displayData(int ... values){
  System.out.println("Number of arguments passed " + values.length);
  for(int i : values){
   System.out.println(i + " ");
  }
 }

 public static void main(String[] args) {
  OverloadingVarargsExp vObj = new OverloadingVarargsExp();
  // four string args
  vObj.displayData("var", "args", "are", "passed");

  // two int args
  vObj.displayData(10, 20);

  // This call is ambiguous
  vObj.displayData();
 }
}

В этой программе, когда мы вызываем метод displayData () без каких-либо параметров, он выдает ошибку, потому что компилятор не уверен, предназначен ли этот вызов метода для displayData(String ... values)илиdisplayData(int ... values)

Таким же образом, если у нас есть перегруженные методы, где у одного есть varargметод одного типа, а у другого метода есть один параметр и varargпараметр того же типа, то у нас также есть неоднозначность - как Exp - displayData(int ... values)иdisplayData(int a, int ... values)

Эти два перегруженных метода всегда будут иметь неоднозначность.

SIW
источник
15

Это Java-способ передачи varargs (аргументов с переменным числом).

Если вы знакомы с C, это похоже на ...синтаксис, используемый в printfфункции:

int printf(const char * format, ...);

но безопасным способом: каждый аргумент должен соответствовать указанному типу (в вашем примере они должны быть всеми String).

Это простой пример того, как вы можете использовать varargs :

class VarargSample {

   public static void PrintMultipleStrings(String... strings) {
      for( String s : strings ) {
          System.out.println(s);
      }
   }

   public static void main(String[] args) {
      PrintMultipleStrings("Hello", "world");
   }
}

...Аргумент на самом деле массив, так что вы могли бы пропускать в String[]качестве параметра.

lornova
источник
11

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

Michaels
источник
5

Также, чтобы пролить некоторый свет, важно знать, что параметры var-arg ограничены одним, и вы не можете иметь несколько параметров var-art. Например, это нелегально:

public void myMethod(String... strings, int ... ints){
// method body
}
Mr.Q
источник
4

Просто подумайте об этом как о ключевом слове paramsв C #, если вы пришли из этого фона :)

Ε Г И І И О
источник
Я программист C #.
Денежно-ориентированный программист
2

Действительно распространенный способ увидеть наглядный пример использования трех точек, присутствующих в одном из самых известных методов в Android AsyncTask (который сегодня используется не слишком часто из-за RXJAVA, не говоря уже о компонентах архитектуры Google), Вы можете найти тысячи примеров, ищущих этот термин, и лучший способ понять и никогда больше не забывать о значении этих трех точек - это то, что они выражают ... сомнение ... как в обычном языке. А именно, не ясно, сколько параметров должно быть передано, может быть 0, может быть 1, может быть больше (массив) ...

trocchietto
источник
1

String... такой же как String[]

import java.lang.*;

public class MyClassTest {

    //public static void main(String... args) { 

    public static void main(String[] args) {
        for(String str: args) {
            System.out.println(str);
        }
    }
}
Уддхав Гаутам
источник
1
Если String...это так же String[], не могли бы вы просто сказать это?
Скотт Хантер
8
Технически это не так, потому что String[]требует аргумент (по крайней мере, пустой массив), тогда как String...нет (см. Ответ выше).
Аурел
0

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

PhantomReference
источник
0
  • Это означает ноль или несколько параметров одного типа данных.
  • Это должен быть последний параметр конструктора или функции.
  • Мы можем иметь только один параметр этого типа в соответствующем конструкторе или функции.

Пример 1:

public class quest1 {

    public quest1(String... mynum) {
        System.out.println("yee haa");
    }

    public static void main(String[] args) {
        quest1 q=new quest1();

        quest1 q1=new quest1("hello");

    }
}

Пример 2:

public class quest1 {

    public quest1(int... at) {
        System.out.println("yee haa");
    }

    public quest1(String... at) {
        System.out.println("yee haa");
    }

    public static void main(String[] args) {
        quest1 q=new quest1("value");

        quest1 q1=new quest1(1);

    }

    public void name(String ... s) {

    }
}

вывод:

да хаа

да хаа

Шубхам Джайн
источник
-1

Синтаксис: (Тройная точка ...) -> Означает, что мы можем добавить ноль или более объектов, передаваемых в аргументах, или передавать массив объектов типа.

public static void main(String[] args){}
public static void main(String... args){}

Определение: 1) Аргумент Object ... - это просто ссылка на массив объектов.

2) ('String []' или String ...) Может обрабатывать любое количество строковых объектов. Внутренне он использует массив объектов ссылочного типа.

i.e. Suppose we pass an Object array to the ... argument - will the resultant argument value be a two-dimensional array - because an Object[] is itself an Object:

3) Если вы хотите вызвать метод с одним аргументом, а он является массивом, вы должны явно обернуть его в

another. method(new Object[]{array}); 
OR 
method((Object)array), which will auto-wrap.

Приложение: в основном используется, когда число аргументов является динамическим (число аргументов известно во время выполнения) и в переопределении. Общее правило - В методе мы можем передавать любые типы и любое количество аргументов. Мы не можем добавлять аргументы объекта (...) перед какими-либо конкретными аргументами. т.е.

void m1(String ..., String s) this is a wrong approach give syntax error.
void m1(String s, String ...); This is a right approach. Must always give last order prefernces.   
Вишал Шет
источник