Argumentos Variadicos (Varargs)

Desde Java 5 se incorporo la posibilidad de tener argumentos variádicos (varargs) en métodos y constructores, dichos argumentos permiten al desarrollador ahorrarse la sobrecarga de métodos o constructores que contienen de 0 a N argumentos del mismo tipo.

Antes de Java 5, había de dos sopas, se tenía que sobrecargar el método, con la límitante para el desarrollador de saber la cantidad máxima y mínima del número de argumentos:

 

Y la segunda sopa sería tener definidos los elementos dentro de un arreglo:

 

En ambos casos los elementos a recibir ya tienen definido un número fínito argumentos recibidos en el primer caso los metodos reciben 1,2 ó 3 y en el segundo solo se recibe 1, pero en ambos casos no nos permitiría llamar al metodo sin argumentos:

 

Los argumentos variádicos (varargs) sirven para este propósito como mencione anteriormente pueden recibir de 0 a N elementos, para representar un argumento variádico es utilizar el simbolo de ellipsis (...) y tiene la siguiente sintaxis:

(Tipo ... variable)

La siguiente clase muestra el uso del ejemplo anterior con varargs:

 

Los varargs en Java tienen las siguientes reglas:

1.- Solo se puede utilizar sólo uno en la firma de un método, si se definen dos o más causará error de compilación.

2.- Si existen otros argumentos el varargs siempre debe declararse al final de todos los argumentos.

3.- El varargs internamente es un arreglo del tipo de dato declarado por lo cual su tamaño no es infiníto, este depende del tamaño máximo de un arreglo de cada implementación de JVM.

4- Los metodos con varargs se pueden sobrecargar y sobreescribir sin embargo no se recomienda hacerlo, según oracle porque hace a los programadores dificil de saber cual método se llamará, y genera algunos problemas de ambiguedad.

Ejemplos de errores de compilación:

 

A continuación un ejemplo de sobrecarga:

 

Veamos un problema de ambiguedad en la sobrecarga de metodos con varargs donde dos o más metodos sobrecargados son suceptibles de llamarse y el compilador marca error:

 

Cabe destacar que el compilador cuando existe sobrecarga primero manda a llamar al metodo con el tipo de dato específico que le acomode: primitivos, promoción de primitivos, wrappers, y al final varargs, en ese orden.

Los varargs pueden generar mensajes de advertencia al ser utilizados con genéricos, debido a que en tiempo de compilación se borran los tipados genéricos, sustituyendolos con un tipo Object o en el caso de varargs lo traduce a un arreglo de Objetos (Object[]), las operaciones de cast o asignación pueden generar problemas de conversión de tipos que el compilador no puede inferir si existe un "heap pollution", ya que no conoce los tipos reales, veamos un ejemplo de ello:

 

Generaría la siguiente salida:

Note: VarargsExample.java uses unchecked or unsafe operations
Note: Recompile with -Xlint:unchecked for details

Recompilamos con: javac -Xlint:unchecked VarargsExample.java y nos mostrara el detalle con el mensaje Possible heap pollution from parameterized vararg type.

Para evitar este warning en Java 7 se introdujo la anotación @SafeVarargs que se debe de utilizar siempre y cuando se este seguro que no se originará un ClassCastException en nuestro código.

El post termina hasta aquí y como siempre si tienen datos de interes o correcciones y/o precisiones comentenlas.

Saludos.

Opciones de visualización de comentarios

Seleccione la forma que prefiera para mostrar los comentarios y haga clic en «Guardar las opciones» para activar los cambios.

También en main

También es válido usar varargs en el método main.

 

Imagen de Cid

Es correcto de hecho cualquier método que contenga como último argumento un arreglo se puede sustituir con un vararg, aunque no siempre es deseable, el caso del main quedo muy ad-hoc porque puedes recibir de 0 a N Strings como argumentos de linea de comando, pero en otras situaciones podria tener comportamientos no deseados como el llamado con 0 argumentos del método en cuestión.

Dejo una liga interesante del tema:

java-method-params-var-args-vs-array