2009-04-20 26 views
176

Tengo miedo de varargs. No sé para qué usarlos.¿Cuándo utiliza varargs en Java?

Además, se siente peligroso dejar que la gente pase tantos argumentos como quieran.

¿Cuál es un ejemplo de contexto que sería un buen lugar para usarlos?

+2

no veo por qué sería 'peligroso'. No es más peligroso que tener un método llamado un gran número de veces con diferentes argumentos. ¿Tiene problemas con la pila? Entonces no debería, porque los varargs se asignan a las matrices que se pasan por referencia. – jfpoilpret

+63

Simplemente quería decir: no hay nada de malo en evitar las características del idioma con las que aún no se siente totalmente cómodo. ¡Mucho mejor que usar funciones que no comprende! – Steven

+2

Es normal tener miedo a lo desconocido. Para obtener más información, lea acerca de las varargs aquí http://docs.oracle.com/javase/tutorial/java/javaOO/arguments.html. Verá, que las varargs no son nada que temer Los varargs son útiles. Saber cómo usar varargs le da la capacidad de escribir métodos como [PrintStream.format] ("http://docs.oracle.com/javase/7/docs/api/java/io/PrintStr eam.html # printf (java.lang.String, java.lang.Object ...) ") :). – Willmore

Respuesta

144

Varargs son útiles por cualquier método que tiene que hacer frente a un número indeterminado de objetos. Un buen ejemplo es String.format. La cadena de formato puede aceptar cualquier cantidad de parámetros, por lo que necesita un mecanismo para pasar en cualquier cantidad de objetos.

String.format("This is an integer: %d", myInt); 
String.format("This is an integer: %d and a string: %s", myInt, myString); 
+4

Un parámetro de matriz también puede recibir un número indeterminado de objetos pero un parámetro varargs permite más flexibilidad y conveniencia en el punto de invocación. Puedes escribir código para construir una matriz y pasarla, o puedes dejar que Java lo haga por ti cuando elijas recibirlo en un parámetro varargs. – H2ONaCl

1

Uso varargs con frecuencia para los constructores que pueden tomar algún tipo de objeto de filtro. Por ejemplo, una gran parte de nuestro sistema basado en Hadoop se basa en un Mapper que maneja la serialización y deserialización de elementos a JSON, y aplica una cantidad de procesadores que toman un elemento de contenido y lo modifican y lo devuelven, o devuelven null rechazar.

77

Una buena regla general sería:

"Uso varargs por cualquier método (o constructor) que necesita una matriz de T (independientemente del tipo T puede ser) como entrada".

Esto facilitará las llamadas a estos métodos (no es necesario hacer new T[]{...}).

Puede ampliar esta regla para incluir métodos con un argumento List<T>, siempre que este argumento sea solo para entrada (es decir, la lista no se modifique con el método).

Además, me abstendría de usar f(Object... args) porque se desliza hacia una forma de programación con API poco claras.

en términos de ejemplos, lo he utilizado en DesignGridLayout, donde puedo añadir varios JComponent s en una llamada:

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

En el código anterior el método add() se define como add(JComponent... components).

Finalmente, la implementación de tales métodos debe tener en cuenta el hecho de que se puede invocar con un vararg vacío. Si desea imponer al menos un argumento, entonces usted tiene que utilizar un truco feo como:

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

Considero que esta mala pasada ya que la implementación del método será menos sencillo que tener sólo T... args en sus argumentos lista.

Espera esto ayuda a aclarar el punto sobre varargs.

+1

¿Consideró agregar una verificación de condición previa 'if (args.length == 0) throw new RuntimeException (" foo ");' en su lugar?(Dado que la persona que llama estaba violando el contrato) –

+23

Bueno, el propósito de una buena API es evitar el uso indebido lo antes posible, por lo que en tiempo de compilación cuando sea posible, de ahí la sugerencia de 'void f (T arg1, T ... args) 'que siempre garantiza que nunca se invoque sin argumentos, sin necesidad de esperar hasta el tiempo de ejecución. – jfpoilpret

+0

Creo que la mayoría de las veces una llamada a una función varargs-only sin argumentos en absoluto equivale a no hacer nada en absoluto. El punto es que no proporcionar ningún argumento a una función varargs es muy probable que no cause un daño considerable. – WorldSEnder

5

que tienen un miedo relacionado varargs-también:

Si la persona que llama pasa en una matriz explícita al método (a diferencia de múltiples parámetros), recibirá una referencia común a la matriz.

Si necesita almacenar esta matriz internamente, es posible que desee clonarla primero para evitar que la persona que llama pueda cambiarla más tarde.

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

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

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

Si bien esto no es realmente diferente de pasar en cualquier tipo de objeto cuyo estado podría cambiar más tarde, ya que la matriz es por lo general (en el caso de una llamada con múltiples argumentos en lugar de una matriz) por uno nuevo creado por el compilador internamente que puede usar con seguridad, este es sin duda el comportamiento inesperado.

+1

Correcto, pero este ejemplo parece un poco rebuscado. ¿Es probable que la gente use tu API de esta manera? – jfpoilpret

+2

Nunca se sabe ... Y especialmente cuando el número de argumentos no está codificado en el lado de la llamada, sino que también se recoge en una lista en un bucle, pasar un conjunto no es tan poco común. – Thilo

+5

Creo que su ejemplo de caso de uso es, en términos generales, no poco probable. Uno podría argumentar que su API no debería usar la matriz de entrada de esta manera, y si lo hace, debe documentarla. –

33

Uso varargs con frecuencia para dar salida a los registros para fines de depuración.

Prácticamente todas las clases en mi aplicación tiene un debugPrint método():

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

Luego, dentro de los métodos de la clase, que tienen llamadas como las siguientes:

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

cuando estoy Estoy satisfecho de que mi código está funcionando. Comente el código en el método debugPrint() para que los registros no contengan demasiada información extraña y no deseada, pero puedo dejar las llamadas individuales a debugPrint() sin comentario. Más adelante, si encuentro un error, simplemente elimino el código de debugPrint() y todas mis llamadas a debugPrint() se reactivan.

Por supuesto, tan sólo pudiera evitar tan fácilmente varargs y hacer lo siguiente en su lugar:

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

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

Sin embargo, en este caso, cuando comento el código debugPrint(), el servidor todavía tiene que pasar por el problema de concatenar todas las variables en cada llamada a debugPrint(), aunque no se haga nada con la cadena resultante. Sin embargo, si uso varargs, el servidor solo tiene que ponerlos en una matriz antes de darse cuenta de que no los necesita. Se ahorra mucho tiempo.

+3

Puede implementar un método de depuración en la superclase para imprimir cualquier objeto utilizando la reflexión. –

11

Los varargs se pueden usar cuando no estamos seguros acerca de la cantidad de argumentos que se deben pasar en un método. Crea un conjunto de parámetros de longitud no especificada en el fondo y dicho parámetro se puede tratar como una matriz en tiempo de ejecución.

Si tenemos un método que está sobrecargado para aceptar diferentes números de parámetros, entonces en lugar de sobrecargar el método en diferentes momentos, podemos simplemente usar el concepto varargs.

También cuando el tipo de parámetros va a variar, el uso de "Object ... test" simplificará mucho el código.

Por ejemplo:

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

Aquí indirectamente una matriz de tipo int (lista) se pasa como parámetro y se trata como una matriz en el código.

Para una mejor comprensión, siga este enlace (que me ha ayudado mucho en la comprensión de este concepto con claridad): http://www.javadb.com/using-varargs-in-java

P.S: A pesar de que tenía miedo de usar varargs cuando no knw ABT. Pero ahora estoy acostumbrado. Como se dice: "Nos aferramos a lo conocido, tememos a lo desconocido", así que solo úsala tanto como puedas y tú también comenzarás a agradar :)

+4

C# Equivalente de varargs es "params". También hace lo mismo y acepta una cantidad variable de parámetros. Consulte esto para una mejor comprensión: http://www.dotnetperls.com/params – Sarvan

8

Varargs es la característica añadida en la versión java 1.5 .

¿Por qué utilizar esto?

  1. ¿Qué sucede si no conoce la cantidad de argumentos para pasar por un método?
  2. ¿Qué sucede si desea pasar un número ilimitado de argumentos a un método?

¿Cómo funciona?

Crea una matriz con los argumentos dados & pasa la matriz al método.

Ejemplo:

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

} 

de salida:

suma es 12

suma es 21

1

En Java doc de Var-args es evidente el uso de argumentos var:

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

sobre el uso que dice:

"¿Cuándo se debe utilizar varargs? Como cliente, debe aprovecharlos siempre que la API los ofrezca. Los usos importantes en las API principales incluyen la reflexión, el formateo de mensajes y la nueva instalación de impresión. Como diseñador de API, debe usarlo con moderación, solo cuando el beneficio sea realmente convincente. En general, no debe sobrecargar un método varargs, o será difícil para los programadores averiguar qué sobrecarga se llama. "

Cuestiones relacionadas