Tengo miedo de los varargs. No sé para qué usarlos.
Además, se siente peligroso dejar que las personas pasen tantos argumentos como quieran.
¿Cuál es un ejemplo de un contexto que sería un buen lugar para usarlos?
Tengo miedo de los varargs. No sé para qué usarlos.
Además, se siente peligroso dejar que las personas pasen tantos argumentos como quieran.
¿Cuál es un ejemplo de un contexto que sería un buen lugar para usarlos?
Respuestas:
Los varargs son útiles para cualquier método que necesite tratar con un número indeterminado de objetos . Un buen ejemplo es String.format
. La cadena de formato puede aceptar cualquier número de parámetros, por lo que necesita un mecanismo para pasar cualquier número de objetos.
String.format("This is an integer: %d", myInt);
String.format("This is an integer: %d and a string: %s", myInt, myString);
Una buena regla general sería:
"Utilice varargs para cualquier método (o constructor) que necesite una matriz de T (cualquiera que sea el tipo T) como entrada".
Eso facilitará las llamadas a estos métodos (no es necesario hacerlo) new T[]{...}
).
Puede ampliar esta regla para incluir métodos con un List<T>
argumento, siempre que este argumento sea solo para entrada (es decir, el método no modifica la lista).
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 usado en DesignGridLayout , donde puedo agregar 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 puede llamarse con un vararg vacío! Si quieres imponer al menos un argumento, entonces debes usar un truco feo como:
void f(T arg1, T... args) {...}
Considero este truco feo porque la implementación del método será menos sencilla que tener T... args
en su lista de argumentos.
Espera que esto ayude a aclarar el punto sobre varargs.
if (args.length == 0) throw new RuntimeException("foo");
lugar? (Dado que la persona que llama estaba violando el contrato)
void f(T arg1, T... args)
que siempre se asegura de que nunca se llame sin argumento, sin necesidad de esperar hasta el tiempo de ejecución.
Utilizo varargs con frecuencia para dar salida a los registros con fines de depuración.
Casi todas las clases de mi aplicación tienen un método debugPrint ():
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, tengo llamadas como las siguientes:
debugPrint("for assignment ", hwId, ", student ", studentId, ", question ",
serialNo, ", the grade is ", grade);
Cuando estoy satisfecho de que mi código funciona, comento 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 comentar. Más tarde, si encuentro un error, simplemente elimino el código debugPrint (), y todas mis llamadas a debugPrint () se reactivan.
Por supuesto, podría evitar 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.
Varargs se puede usar cuando no estamos seguros de la cantidad de argumentos que se pasarán en un método. Crea una matriz de parámetros de longitud no especificada en segundo plano y dicho parámetro puede tratarse como una matriz en tiempo de ejecución.
Si tenemos un método que está sobrecargado para aceptar un número diferente de parámetros, entonces, en lugar de sobrecargar el método en diferentes momentos, simplemente podemos usar el concepto varargs.
Además, cuando el tipo de los 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 (me ayudó mucho a comprender este concepto claramente): http://www.javadb.com/using-varargs-in-java
PD: Incluso tenía miedo de usar varargs cuando no lo sabía. Pero ahora estoy acostumbrado. Como se dice: "Nos aferramos a lo conocido, tememos a lo desconocido", así que úsalo tanto como puedas y a ti también te va a gustar :)
Varargs es la característica agregada en la versión 1.5 de Java.
¿Por qué usar esto?
¿Cómo funciona esto?
Crea una matriz con los argumentos dados y 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 );
}
}
Salida:
2
suma es 12
3
suma es 21
También tengo un miedo relacionado con los varargs:
Si la persona que llama pasa una matriz explícita al método (en oposición a múltiples parámetros), recibirá una referencia compartida a esa 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 cualquier tipo de objeto cuyo estado podría cambiar más tarde, ya que la matriz es generalmente (en caso de una llamada con múltiples argumentos en lugar de una matriz) una nueva creada internamente por el compilador que puede uso, este es ciertamente un comportamiento inesperado.
Utilizo varargs con frecuencia para 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 un valor nulo rechazar.
En Java doc de Var-Args está bastante claro el uso de var args:
http://docs.oracle.com/javase/1.5.0/docs/guide/language/varargs.html
sobre el uso dice:
"Entonces, ¿cuándo debería usar varargs? Como cliente, debe aprovecharlos cada vez que la API los ofrezca. Los usos importantes en las API centrales incluyen reflexión, formato de mensajes y la nueva función printf. Como diseñador de API, debe usarlos con moderación, solo cuando el beneficio es realmente convincente. En términos generales, no debe sobrecargar un método varargs, o será difícil para los programadores averiguar qué sobrecarga se llama ".