Varargs en Java: número variable de argumentos en Java

Es posible implementar métodos con un número variable de argumentos en Java, desde la versión 5.

Las condiciones a cumplir son las siguientes:

  1. Los parámetros variables tienen todos el mismo tipo (o son instancias del mismo objeto).
  2. Hay cero o más parámetros variables.
  3. Sólo hay un conjunto de parámetros variables.
  4. El conjunto de parámetros variables viene al final de la definición del método.

Como ejemplo, la definición del método java.io.PrintStream.printf():

public PrintStream printf(String format,
                          Object... args)

Uso

Veamos un ejemplo sencillo: un método que devuelve la suma de un número variable de enteros:

public static int sum(int... args)
{
   int result=0;
   for(int a:args)
   {
      result+=a;
   }
   return result;
}

Ejemplo de uso del método:

System.out.printf("0 %d\n", sum()); // prints "0 0"
System.out.printf("1 %d\n", sum(1)); // prints "1 1"
System.out.printf("2 %d\n", sum(1, 2)); // prints "2 3"
System.out.printf("3 %d\n", sum(1, 2, 3)); // prints "3 6"
System.out.printf("4 %d\n", sum(1, 2, 3, 4)); // prints "4 10"

Supongamos que queremos forzar a que haya, al menos, dos enteros (no tiene sentido la suma de 0 ó 1 enteros):

public static int sum(int arg0, int arg1, int... args)
{
   int result=arg0+arg1;
   for(int a:args)
   {
      result+=a;
   }
   return result;
}

Ahora no podemos llamar a la rutina sin argumentos. Un ejemplo de llamada:

System.out.printf("6 %d\n", sum(1, 2, new int[]{2, 3, 4, 5})); // prints "5 17"

Object

Uso básico con objetos:

public static int objector(Object... args)
{
   return args.length;
}

Probamos con unas cadenas (String):

String[] strings = new String[]{"one", "two", "three"};
Object[] objects = new Object[]{Integer.valueOf(1), Boolean.TRUE, "three"};
System.out.printf("strings %d\n", objector(strings)); // prints "strings 3"
System.out.printf("objects %d\n", objector(objects)); // prints "objects 3"

De la misma manera, si requerimos al menos un objeto:

public static int objector(Object arg0, Object... args)
{
   return args.length;
}

Si ejecutamos los printf del ejemplo de código anterior, utilizando la nueva versión de la rutina objector, veremos que devuelve una longitud cero. Esto se debe a que el array es un objeto en sí, y está siendo pasado a la rutina como primer argumento.

En un caso como este, podemos manejar el caso en que el número de argumentos es igual a cero de esta manera:

public static void objector(Object... args)
{
   if(args.length==0)
   {
      // special case
   }
   else
   {
      // handle arguments
   }
}

En este caso, un mal uso quedaría de manifiesto en tiempo de compilación. Esto te da la opción de cambiar la interfaz.

Conclusión

Ya que los objetos pasados como argumentos van a ser tratados como un array de tipo Object[] (utilizando reflexión), parece sólo tiene sentido utilizar la versión Object… varargs si el método forma parte de un API y va a ser utilizado por otros.

Autoboxing

Otra cuestión a tener en cuenta es que podemos utilizar el Autoboxing, también introducido en la versión 5 de Java. Esto permite la conversión automática entre tipos y sus objetos correspondientes. Esto funciona si, por ejemplo, pasamos varios objetos Integer a una rutina con argumentos int… args. Sin embargo, no funciona si pasamos un Integer[], pues Java no puede convertirlo automáticamente a int[].

public static int inter(int... args)
{
   return args.length;
}
int[] ints = new int[]{ 1, 2, 3, 4, 5 };
Integer[] integers = new Integer[]{ 1, 2, 3, 4, 5 };
System.out.printf("ints %d\n", inter(ints)); // prints "ints 5"
System.out.printf("Integer %d\n", inter(Integer.valueOf(1), Integer.valueOf(2))); // prints Integer 2"
System.out.printf("Integer[] %d\n", inter(integers)); // compiler error

Si que funcionaría si lo hiciéramos al revés. Es decir, si el argumento esperado es de tipo Integer… args, podemos pasar un int[].

Vía | javaranch

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>