Java, 3 puntos en parámetros

822

¿Qué significan los 3 puntos en el siguiente método?

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

Respuestas:

987

Significa que se pueden pasar cero o más objetos String (o una matriz de ellos) como argumento (s) para ese método.

Consulte la sección "Número arbitrario de argumentos" aquí: http://java.sun.com/docs/books/tutorial/java/javaOO/arguments.html#varargs

En su ejemplo, podría llamarlo como cualquiera de los siguientes:

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

Nota importante: Los argumentos pasados ​​de esta manera siempre son una matriz, incluso si solo hay uno. Asegúrese de tratarlo de esa manera en el cuerpo del método.

Nota importante 2: El argumento que obtiene el ...debe ser el último en la firma del método. Entonces, myMethod(int i, String... strings)está bien, pero myMethod(String... strings, int i)no está bien.

Gracias a Vash por las aclaraciones en su comentario.

kiswa
fuente
112
Estás equivocado, en ese "uno o más", con varargs podemos especificar 0 o más, y este tiene que ser siempre el último parámetro en el método. El método x (String ... params) se puede llamar como x () o el método y (String pram, String ... params) se puede llamar como y ("1")
Damian Leszczyński - Vash
2
Ojalá si esto hubiera funcionado también. myMethod ("one", "two", "three", new String [] {"a", "b", "c" "});
2sb
2
¿Por qué se le permite dar al método 0 parámetros? Lo más probable es que conduzca a ArrayIndexOutOfBoundsException. Ahora siempre tienes que tomar ese caso en consideración.
Olle Söderström
11
Porque son opcionales. Depende del desarrollador que decidió usar argumentos opcionales para implementar adecuadamente el método para manejar tener cero o más de ellos.
kiswa
@ OlleSöderström Otra razón es que el parámetro formal se convierte en una matriz en tiempo de compilación. Eso significa que pasar una matriz produce el mismo resultado. Como la longitud de una matriz no se conoce en el momento de la compilación, la restricción para pasar al menos un elemento podría omitirse simplemente llamando someMethod(new SomeType[] { }). Eso sería un truco, ¿no?
MC Emperor
124

Esa característica se llama varargs , y es una característica introducida en Java 5. Significa que la función puede recibir múltiples Stringargumentos:

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

Luego, puede usar la Stringvar como una matriz:

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

Esta respuesta se basa en gran medida en la de kiswa y Lorenzo ... y también en el comentario de Graphain.

Cristian
fuente
13
Cuando el código llega al bytecode, es una matriz. Todo lo demás es sintaxis compatible solo con el compilador.
Donal Fellows
Esta respuesta se basa en gran medida en la de kiswa y Lorenzo si leo las ediciones correctamente.
Matt Mitchell
3
@Graph 'es mejor editar tu respuesta y hacerla más correcta que dejarla sola. Y si otra respuesta es la fuente de su mejora, entonces continúa. Al menos es honesto al respecto (y supongo que votó por las otras respuestas que lo ayudaron ... ¿verdad?).
1
@ Será honesto después de que lo señalé, lo cual es lo suficientemente bueno. Gracias por mirar.
Matt Mitchell
23

Es Varargs :)

La abreviatura varargs para argumentos de longitud variable es una característica que permite que el método acepte un número variable de argumentos (cero o más). Con varargs se ha vuelto simple crear métodos que necesitan tomar un número variable de argumentos. La característica de argumento variable se ha agregado en Java 5.

Sintaxis de varargs

Un vararg está segmentado por tres puntos suspensivos (tres puntos) después del tipo de datos, su forma general es

return_type method_name(data_type ... variableName){
}  

Necesidad de varargs

Antes de Java 5, en caso de que fuera necesario un número variable de argumentos, había dos formas de manejarlo.

Si el número máximo de argumentos que un método puede tomar era pequeño y conocido, entonces podrían crearse versiones sobrecargadas del método. Si el número máximo de argumentos que un método podría tomar era grande o desconocido, entonces el enfoque consistía en colocar esos argumentos en una matriz y pasarlos a un método que tomara la matriz como parámetro. Estos 2 enfoques eran propensos a errores, construyendo una matriz de parámetros cada vez y difíciles de mantener, ya que la adición de nuevos argumentos puede resultar en escribir un nuevo método sobrecargado.

Ventajas de varargs

Ofrece una opción mucho más simple. Menos código ya que no es necesario escribir métodos sobrecargados.

Ejemplo de 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

Del programa se puede ver que la longitud se usa aquí para encontrar el número de argumentos pasados ​​al método. Es posible porque los varargs se pasan implícitamente como una matriz. Los argumentos que se pasan como varargs se almacenan en una matriz que se denomina por el nombre dado a varargs. En este programa, el nombre de la matriz es valores. También tenga en cuenta que el método se llama con un número diferente de argumentos, primero con cuatro argumentos, luego con tres argumentos y luego con cero argumentos. Todas estas llamadas son manejadas por el mismo método que toma varargs.

Restricción con varargs

Es posible tener otros parámetros con el parámetro varargs en un método, sin embargo, en ese caso, el parámetro varargs debe ser el último parámetro declarado por el método.

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

Otra restricción con varargs es que solo debe haber un parámetro varargs.

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

Sobrecarga de métodos varargs

Es posible sobrecargar un método que toma el parámetro varargs. El método Varargs se puede sobrecargar por:

Los tipos de su parámetro vararg pueden ser diferentes. Al agregar otros parámetros. Ejemplo de sobrecarga del método 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 y sobrecarga de ambigüedad

En algunos casos, la llamada puede ser ambigua mientras hemos sobrecargado el método varargs. Veamos un ejemplo.

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

En este programa, cuando hacemos una llamada al método displayData () sin ningún parámetro, arroja un error, porque el compilador no está seguro de si esta llamada al método es para displayData(String ... values)odisplayData(int ... values)

De la misma manera, si tenemos métodos sobrecargados donde uno tiene el varargmétodo de un tipo y otro método tiene un parámetro y un varargparámetro del mismo tipo, entonces también tenemos la ambigüedad, como Exp, displayData(int ... values)ydisplayData(int a, int ... values)

Estos dos métodos sobrecargados siempre tendrán ambigüedad.

SIW
fuente
15

Esta es la forma Java de pasar varargs (argumentos de números variables).

Si está familiarizado con C, esto es similar a la ...sintaxis utilizada en la printffunción:

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

pero de forma segura: cada argumento debe cumplir con el tipo especificado (en su muestra, deberían ser todos String).

Esta es una muestra simple de cómo puede usar 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");
   }
}

El ...argumento es en realidad una matriz, por lo que podría pasar a String[]como parámetro.

lornova
fuente
11

Podría decirse que es un ejemplo de azúcar sintáctico, ya que de todos modos se implementa como una matriz (lo que no significa que sea inútil): prefiero pasar una matriz para mantenerla clara y también declarar métodos con matrices de un tipo dado. Sin embargo, es más una opinión que una respuesta.

MichaelS
fuente
5

También para arrojar algo de luz, es importante saber que los parámetros var-arg están limitados a uno y no puede tener varios parámetros de var-art. Por ejemplo, esto es ilegal:

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

Solo piense en ella como la palabra clave paramsen C #, si viene de ese contexto :)

Ε Г И І И О
fuente
Soy un programador de C #.
Programador orientado al dinero
2

Una forma muy común de ver un ejemplo claro del uso de los tres puntos está presente en uno de los métodos más famosos en Android AsyncTask (que hoy no se usa demasiado debido a RXJAVA, sin mencionar los componentes de Google Architecture), puedes encontrar miles de ejemplos buscando este término, y la mejor manera de entender y nunca más olvidar el significado de los tres puntos es que expresan una ... duda ... al igual que en el lenguaje común. Es decir, no está claro el número de parámetros que deben pasarse, podría ser 0, podría ser 1 podría ser más (una matriz) ...

trocchietto
fuente
1

String... es lo mismo que 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
fuente
1
Si String...es lo mismo que String[], ¿no podrías decir eso?
Scott Hunter
8
Técnicamente no es cierto porque String[]requiere un argumento (al menos una matriz vacía) mientras String...que no (ver la respuesta anterior).
Aurel
0

Además de las otras respuestas bien escritas, una ventaja varagrsque encontré útil es que, cuando llamo a un método con una matriz como tipo de parámetro, me quita el dolor de crear una matriz; agregue elementos y luego envíelo. En cambio, puedo llamar al método con todos los valores que quiera; de cero a muchos.

PhantomReference
fuente
0
  • Significa cero o múltiples parámetros del mismo tipo de datos.
  • Debe ser el último parámetro del constructor o función.
  • Solo podemos tener un parámetro de este tipo en el respectivo constructor o función.

Ejemplo 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");

    }
}

Ejemplo 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) {

    }
}

salida:

yee haa

yee haa

Shubham Jain
fuente
-1

Sintaxis: (Triple punto ...) -> Significa que podemos agregar cero o más objetos pasados ​​en un argumento o pasar una matriz de objetos tipo.

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

Definición: 1) El argumento Objeto ... es solo una referencia a una matriz de Objetos.

2) ('Cadena []' o Cadena ...) Puede manejar cualquier número de objetos de cadena. Internamente utiliza una matriz de objetos de tipo de referencia.

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) Si desea llamar al método con un solo argumento y resulta ser una matriz, debe envolverlo explícitamente en

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

Aplicación: Se utiliza principalmente cuando el número de argumentos es dinámico (número de argumentos conocidos en tiempo de ejecución) y en la anulación. Regla general : en el método podemos pasar cualquier tipo y cualquier número de argumentos. No podemos agregar argumentos de objeto (...) antes de cualquier argumento específico. es decir

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
fuente