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


822

Що означають 3 крапки у наведеному нижче методі?

public void myMethod(String... strings){
    // method body
}

Відповіді:


987

Це означає, що як аргумент (и) для цього методу можуть передаватися нульові або більше об'єктів 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: Аргумент, який отримує ...must, повинен бути останнім у підписі методу. Отже, myMethod(int i, String... strings)добре, але myMethod(String... strings, int i)не гаразд.

Дякуємо Вашу за роз’яснення у своєму коментарі.


112
Ви помиляєтесь, що у "одному чи кількох", за допомогою варагрів ми можемо вказати 0 або більше, і це завжди має бути останній параметр у методі. Метод x (String ... params) може називатися як x () або метод y (String pram, String ... params) можна викликати як y ("1")
Damian Leszczyński - Vash

2
Я хотів би, якби це теж спрацювало. myMethod ("один", "два", "три", новий рядок [] {"a", "b", "c" "});
2sb,

2
Чому дозволено надати методу 0 параметрів? Це, швидше за все, призведе до ArrayIndexOutOfBoundsException. Тепер ви завжди повинні враховувати цю справу.
Olle Söderström

11
Тому що вони необов’язкові. Розробник вирішив використати необов'язкові аргументи, щоб правильно реалізувати метод для обробки нуля або більше.
kiswa

@ OlleSöderström Ще одна причина полягає в тому, що формальний параметр перетворюється на масив під час компіляції. Це означає, що проходження масиву дає той самий результат. Оскільки довжина масиву не відома під час компіляції, обмеження на передачу принаймні одного елемента може бути обійдене простим викликом someMethod(new SomeType[] { }). Це було б злом, чи не так?
MC імператор

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]
    }
}

Ця відповідь значною мірою запозичується з коментарів Кісва та Лоренцо ..., а також з коментаря Графаїна.


13
Коли код потрапляє в байт - код, він є масивом. Все інше - синтаксис, що підтримується саме компілятором.
стипендіати доналу

Ця відповідь сильно запозичується у Кісви та Лоренцо, якщо я правильно прочитав правки.
Метт Мітчелл

3
@ Графічно краще відредагувати свою відповідь і зробити її більш правильною, ніж залишити її в спокої. І якщо інша відповідь є джерелом вашого вдосконалення, то це іде. Принаймні, він чесний з цього приводу (і я припускаю, що він підтримав інші відповіді, які допомогли йому ... правда?).

1
@ Буде він чесним після того, як я вказав, що це досить добре. Дякуємо, що подивилися.
Метт Мітчелл

23

Це вараги :)

Короткий зміст varargs для аргументів змінної довжини - це функція, яка дозволяє методу приймати змінну кількість аргументів (нуль або більше). За допомогою varargs стало просто створювати методи, яким потрібно брати змінну кількість аргументів. В Java 5 додана особливість аргументу змінної.

Синтаксис вараг

Вараг розділяється трьома еліпсисами (трьома крапками) за типом даних, його загальною формою є

return_type method_name(data_type ... variableName){
}  

Потреба у вараг

До Java 5, якщо була необхідна змінна кількість аргументів, існували два способи впоратися з цим

Якщо максимальна кількість аргументів, який може взяти метод, була невеликою і відомою, тоді можна було б створити перевантажені версії методу. Якщо максимальна кількість аргументів, які може взяти метод, була великою або / і невідомою, тоді підхід полягав у тому, щоб розмістити ці аргументи в масиві та передати їх методу, який приймає масив як параметр. Ці два підходи були схильними до помилок - кожен раз створювали масив параметрів і їх важко підтримувати - оскільки додавання нового аргументу може призвести до написання нового перевантаженого методу.

Переваги вараг

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

Приклад вараг

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 повинен бути останнім параметром, оголошеним методом.

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 може бути перевантажений -

Типи його параметра 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. Подивимось приклад

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)

Ці два перевантажені методи завжди матимуть неоднозначність.


15

Це спосіб передачі варагів Java (аргументи змінної кількості).

Якщо ви знайомі з 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[]якості параметра.


11

Можливо, це приклад синтаксичного цукру, оскільки він реалізований як масив у будь-якому випадку (що не означає, що він марний) - я вважаю за краще передавати масив, щоб він був чітким, а також оголошував методи з масивами заданого типу. Радше думка, ніж відповідь.


5

Крім того, щоб пролити трохи світла, важливо знати, що параметри var-arg обмежені одним, і ви не можете мати кілька параметрів var-art. Наприклад, це нелігально:

public void myMethod(String... strings, int ... ints){
// method body
}


2

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


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я вважав корисним, полягає в тому, що коли я викликаю метод з масивом як тип параметра, він знімає біль при створенні масиву; додайте елементи, а потім надішліть. Натомість я можу просто викликати метод з такою кількістю значень, скільки мені хочеться; від нуля до багатьох.


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.   
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.