Java, 3 kropki w parametrach

822

Co oznaczają 3 kropki w poniższej metodzie?

public void myMethod(String... strings){
    // method body
}
Vikram
źródło

Odpowiedzi:

987

Oznacza to, że zero lub więcej obiektów String (lub ich tablica) może zostać przekazanych jako argument (y) dla tej metody.

Zobacz sekcję „Arbitrary Number of Arguments” tutaj: http://java.sun.com/docs/books/tutorial/java/javaOO/arguments.html#varargs

W twoim przykładzie możesz nazwać to dowolną z następujących czynności:

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

Ważna uwaga: Argumenty przekazywane w ten sposób są zawsze tablicami - nawet jeśli istnieje tylko jeden. Upewnij się, że traktujesz to w ten sposób w treści metody.

Ważna uwaga 2: Argument, który pobiera wartość ...musi być ostatnim w sygnaturze metody. Więc myMethod(int i, String... strings)jest w porządku, ale myMethod(String... strings, int i)nie jest w porządku.

Dzięki Vashowi za wyjaśnienia w jego komentarzu.

kiswa
źródło
112
Mylisz się, że w tym „jednym lub więcej” z varargs możemy określić 0 lub więcej, i to musi być zawsze ostatni parametr w metodzie. Metodę x (String ... params) można wywołać jako x () lub metodę y (String wózka, String ... params) można wywołać jako y („1”)
Damian Leszczyński - Vash
2
Chciałbym, żeby to też zadziałało. myMethod („jeden”, „dwa”, „trzy”, nowy ciąg [] {„a”, „b”, „c” ”});
2sb
2
Dlaczego możesz podać metodzie 0 parametrów? To najprawdopodobniej doprowadzi do ArrayIndexOutOfBoundsException. Teraz zawsze musisz wziąć pod uwagę tę sprawę.
Olle Söderström
11
Ponieważ są opcjonalne. To programista zdecydował się użyć opcjonalnych argumentów, aby poprawnie zaimplementować metodę obsługi zerowej lub większej liczby z nich.
kiswa
@ OlleSöderström Innym powodem jest przekonwertowanie parametru formalnego na tablicę w czasie kompilacji. Oznacza to, że przekazanie do tablicy daje ten sam wynik. Ponieważ długość tablicy nie jest znana w czasie kompilacji, ograniczenie do przekazania co najmniej jednego elementu można ominąć, po prostu wywołując someMethod(new SomeType[] { }). To byłby hack, prawda?
MC Cesarz
124

Ta funkcja nazywa się varargs i jest to funkcja wprowadzona w Javie 5. Oznacza to, że funkcja może odbierać wiele Stringargumentów:

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

Następnie możesz użyć Stringvar jako tablicy:

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

Ta odpowiedź mocno zapożycza od Kiswy i Lorenza ... a także od komentarza Graphaina.

Cristian
źródło
13
Gdy kod trafi do kodu bajtowego, jest to tablica. Cała reszta jest obsługiwana przez tylko kompilator.
Donal Fellows
Ta odpowiedź mocno zapożycza od Kiswy i Lorenza, jeśli poprawnie odczytam zmiany.
Matt Mitchell,
3
@Graph 'lepiej jest edytować swoją odpowiedź i sprawić, by była bardziej poprawna niż pozostawić ją w spokoju. A jeśli inna odpowiedź jest źródłem twojego ulepszenia, to tak jest. Przynajmniej jest w tym szczery (i zakładam, że głosował za innymi odpowiedziami, które pomogły mu ... prawda?).
1
@ Czy będzie uczciwy po tym, jak wskazałem, co jest w porządku. Dziękuję za uwagę.
Matt Mitchell,
23

To Varargs :)

Skróty varargs dla argumentów o zmiennej długości to funkcja, która pozwala metodzie zaakceptować zmienną liczbę argumentów (zero lub więcej). Dzięki varargs stało się proste tworzenie metod, które muszą przyjmować zmienną liczbę argumentów. Funkcja zmiennej argument została dodana w Javie 5.

Składnia varargs

Vararg jest oddzielony trzema elipsami (trzy kropki) po typie danych, jego ogólna postać to

return_type method_name(data_type ... variableName){
}  

Potrzeba varargs

W wersjach wcześniejszych niż Java 5, w przypadku gdy potrzebna była zmienna liczba argumentów, istniały dwa sposoby jej obsługi

Jeśli maksymalna liczba argumentów, jaką może przyjąć metoda, była niewielka i znana, można by stworzyć przeciążone wersje metody. Jeśli maksymalna liczba argumentów, które może przyjąć metoda, była duża lub nieznana, wówczas podejście polegało na umieszczeniu tych argumentów w tablicy i przekazaniu ich do metody, która przyjmuje tablicę jako parametr. Te dwa podejścia były podatne na błędy - konstruowanie tablicy parametrów za każdym razem i trudne do utrzymania - ponieważ dodanie nowego argumentu może spowodować napisanie nowej, przeciążonej metody.

Zalety varargs

Oferuje znacznie prostszą opcję. Mniej kodu, ponieważ nie trzeba pisać przeciążonych metod.

Przykład 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

Z programu widać, że długość jest tutaj używana do znalezienia liczby argumentów przekazanych do metody. Jest to możliwe, ponieważ varargs są domyślnie przekazywane jako tablica. Wszelkie argumenty przekazywane jako varargs są przechowywane w tablicy, do której odwołuje się nazwa nadana varargs. W tym programie nazwa tablicy to wartości. Zauważ też, że metoda jest wywoływana z inną liczbą argumentów, najpierw wywołanie z czterema argumentami, następnie trzema argumentami, a następnie z zerowymi argumentami. Wszystkie te wywołania są obsługiwane tą samą metodą, która przyjmuje varargs.

Ograniczenia dotyczące varargs

Możliwe jest posiadanie innych parametrów z parametrem varargs w metodzie, jednak w takim przypadku parametr varargs musi być ostatnim parametrem zadeklarowanym przez metodę.

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

Innym ograniczeniem dotyczącym varargs jest to, że musi istnieć tylko jeden parametr varargs.

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

Przeciążanie metod varargs

Możliwe jest przeciążenie metody przyjmującej parametr varargs. Metoda Varargs może być przeciążona przez -

Rodzaje jego parametru vararg mogą być różne. Dodając inne parametry. Przykład metody przeciążania 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 i przeciążanie niejednoznaczności

W niektórych przypadkach wywołanie może być niejednoznaczne, podczas gdy mamy przeciążoną metodę varargs. Zobaczmy przykład

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();
 }
}

W tym programie, gdy wywołujemy metodę displayData () bez żadnego parametru, generuje błąd, ponieważ kompilator nie jest pewien, czy to wywołanie metody jest dla displayData(String ... values)czydisplayData(int ... values)

Taki sam sposób, jeśli mamy przeciążone metody, w których jedna ma varargmetodę jednego typu, a inna metoda ma jeden parametr i varargparametr tego samego typu, wówczas mamy również dwuznaczność - As Exp - displayData(int ... values)idisplayData(int a, int ... values)

Te dwie przeciążone metody zawsze będą niejednoznaczne.

SIW
źródło
15

To jest Java sposób przekazywania varargs (argumenty o zmiennej liczbie).

Jeśli znasz C, jest to podobne do ...używanej składni printf:

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

ale w sposób bezpieczny: każdy argument musi być zgodny z określonym typem (w twojej próbce powinny być wszystkie String).

Oto prosta próbka użycia 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");
   }
}

...Argument jest rzeczywiście tablicą, więc można przekazać String[]jako parametr.

lornova
źródło
11

Prawdopodobnie jest to przykład cukru syntaktycznego, ponieważ i tak jest on zaimplementowany jako tablica (co nie znaczy, że jest bezużyteczny) - wolę przekazywać tablicę, aby była czysta, a także deklarować metody z tablicami danego typu. Jednak raczej opinia niż odpowiedź.

MichaelS
źródło
5

Aby rzucić nieco światła, ważne jest, aby wiedzieć, że parametry var-arg są ograniczone do jednego i nie można mieć kilku parametrów var-art. Na przykład jest to nielogiczne:

public void myMethod(String... strings, int ... ints){
// method body
}
Mr.Q
źródło
4

Pomyśl o tym jako o słowie kluczowym paramsw C #, jeśli pochodzisz z tego tła :)

Ε Г И І И О
źródło
Jestem programistą C #.
Programista zorientowany na pieniądze
2

Naprawdę powszechny sposób, aby zobaczyć wyraźny przykład użycia trzech kropek, który jest obecny w jednej z najbardziej znanych metod w AndyncTask Androida (który dziś nie jest zbyt często używany z powodu RXJAVA, nie wspominając o komponentach architektury Google), możesz znaleźć tysiące przykładów szukających tego terminu, a najlepszym sposobem na zrozumienie i nigdy nie zapomnienie znaczenia trzech kropek jest to, że wyrażają one ... wątpliwości ... tak jak we wspólnym języku. Mianowicie nie jest jasne, ile parametrów musi zostać przekazanych, może wynosić 0, może być 1 może być więcej (tablica) ...

trocchietto
źródło
1

String... jest taki sam jak 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);
        }
    }
}
Uddhav Gautam
źródło
1
Jeśli String...to to samo String[], czy nie możesz tak po prostu powiedzieć?
Scott Hunter,
8
Technicznie nieprawda, ponieważ String[]wymaga argumentu (przynajmniej pustej tablicy), podczas String...gdy nie (patrz odpowiedź powyżej).
Aurel
0

Dodając do innych dobrze napisanych odpowiedzi, zaletą, która varagrsuważam za przydatną, jest to, że kiedy wywołuję metodę z tablicą jako typ parametru, eliminuje to ból związany z tworzeniem tablicy; dodaj elementy, a następnie wyślij je. Zamiast tego mogę po prostu wywołać metodę z dowolną liczbą wartości; od zera do wielu.

PhantomReference
źródło
0
  • Oznacza zero lub wiele parametrów tego samego typu danych.
  • Musi to być ostatni parametr konstruktora lub funkcji.
  • Możemy mieć tylko jeden parametr tego typu w odpowiednim konstruktorze lub funkcji.

Przykład 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");

    }
}

Przykład 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) {

    }
}

wynik:

yee haa

yee haa

Shubham Jain
źródło
-1

Składnia: (Potrójna kropka ...) -> Oznacza, że ​​możemy dodać zero lub więcej obiektów przekazanych w argumentach lub przekazać tablicę typu obiektowego.

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

Definicja: 1) Argument Object ... jest po prostu odniesieniem do tablicy Objects.

2) („String []” lub String ...) Może obsłużyć dowolną liczbę obiektów string. Wewnętrznie wykorzystuje tablicę obiektu typu referencyjnego.

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) Jeśli chcesz wywołać metodę z jednym argumentem i okazuje się, że jest to tablica, musisz jawnie ją owinąć

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

Zastosowanie: Używany głównie, gdy liczba argumentów jest dynamiczna (liczba argumentów znana w czasie wykonywania) i podczas zastępowania. Ogólna zasada - w metodzie możemy przekazać dowolne typy i dowolną liczbę argumentów. Nie możemy dodawać argumentów obiektowych (...) przed żadnymi konkretnymi argumentami. to znaczy

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.   
Vishal Sheth
źródło