Menu

Varargs en Java: métodos que aceptan cualquier número de argumentos

Cómo los varargs (...) de Java permiten que un método acepte cualquier número de argumentos, cómo se convierten en un arreglo, la regla de un solo vararg al final, y las trampas de la llamada vacía y la ambigüedad.

Esta página incluye editores ejecutables: edita, ejecuta y ve el resultado al instante.

Un método, cualquier número de argumentos

A veces no sabes de antemano cuántos argumentos necesita un método. En un momento quieres max(3, 9) y al siguiente max(1, 7, 4, 2, 8). Sin varargs tendrías que escribir una sobrecarga para cada cantidad u obligar a quien llama a construir un arreglo. Los varargs - abreviatura de argumentos variables - permiten que un solo método acepte cero, uno o muchos valores del mismo tipo.

Se declaran poniendo tres puntos (...) después del tipo del parámetro:

Quien llama pasa valores sueltos; dentro del método numbers es un arreglo real. Esa es toda la idea: el compilador empaqueta los argumentos en un arreglo por ti.

Los varargs son solo un arreglo

No hay magia en tiempo de ejecución. Un parámetro declarado int... numbers es exactamente un int[] una vez que estás dentro del método. Puedes consultar su length, indexarlo y recorrerlo como cualquier otro arreglo.

Como es realmente un arreglo, también puedes entregarle a un método varargs un arreglo que ya tengas: acepta ambas formas:

Las reglas: último y uno solo

Dos reglas mantienen los varargs sin ambigüedad, y el compilador las hace cumplir ambas:

  1. El parámetro varargs debe ser el último. Los parámetros normales van primero, y luego el parámetro ... absorbe todo lo que quede.
  2. Un método puede tener como máximo un parámetro varargs. Dos harían imposible saber dónde termina uno y empieza el siguiente.

Esto compila. Pero poner los varargs primero - static void log(Object... values, String level) - es un error de compilación: varargs parameter must be the last. El parámetro obligatorio level siempre precede al ....

Dónde ya usas varargs

Has estado llamando a métodos varargs todo el tiempo. System.out.printf y String.format son los ejemplos clásicos: su segundo parámetro es Object... args:

List.of(...), Arrays.asList(...) y muchas APIs de estilo constructor también son varargs. Por eso puedes pasarles cualquier número de elementos sin envolver nada en un arreglo tú mismo.

Varargs y sobrecarga

Los varargs y la sobrecarga interactúan de una manera sorprendente. Cuando una sobrecarga normal y una sobrecarga varargs podrían coincidir ambas con una llamada, Java prefiere la más específica: gana el método de aridad fija:

pick(1, 2) coincide con ambas, pero Java elige la sobrecarga sin varargs porque encaja mejor. El método varargs solo se ejecuta cuando ninguna sobrecarga de aridad fija coincide. Esto suele ser lo que quieres, pero significa que añadir una sobrecarga varargs puede cambiar silenciosamente a qué método se resuelve una llamada.

Cuidado con las llamadas vacías y con null

Dos trampas pillan a la gente. Primera: llamar a un método varargs sin argumentos le entrega al método un arreglo vacío, no null, así que numbers.length es 0 y el bucle no hace nada. No necesitas una comprobación de null para el caso sin argumentos:

Segunda: pasar un null literal es ambiguo y peligroso: Java puede interpretar count(null) como "todo el arreglo de varargs es null" en lugar de "un elemento null", lo que luego lanza una NullPointerException cuando lees su length. Si realmente quieres decir un único elemento null, sé explícito con count((Object) null).

Siguiente: Clases

Los varargs completan lo que puedes hacer con los parámetros de métodos: listas de argumentos flexibles encima de la sobrecarga. Hasta ahora los métodos han vivido sueltos en una clase con static. A continuación verás cómo funcionan realmente las clases: agrupar datos (campos) y comportamiento (métodos) en tus propios tipos, que es el corazón de la programación orientada a objetos en Java.

Preguntas frecuentes

¿Qué son los varargs en Java?

Los varargs (argumentos variables) permiten que un método acepte cualquier número de argumentos del mismo tipo. Se declaran poniendo ... después del tipo: int sum(int... numbers). Quien llama puede pasar cero, uno o muchos valores, y dentro del método numbers es un arreglo normal. Es azúcar sintáctico: Java recoge los argumentos sueltos en un arreglo por ti.

¿Puede un método de Java tener más de un parámetro varargs?

No. Un método puede tener como máximo un parámetro varargs, y debe ser el último de la lista de parámetros; por ejemplo void log(String level, Object... values). Si no fuera el último, Java no sabría dónde termina la parte de longitud variable y dónde empieza el siguiente parámetro. Los parámetros normales siempre van antes del parámetro ....

¿Cuál es la diferencia entre varargs y un parámetro de tipo arreglo en Java?

Son casi lo mismo en tiempo de ejecución: un parámetro varargs int... es un int[] dentro del método. La diferencia está en el punto de llamada: con varargs escribes sum(1, 2, 3) (valores sueltos), mientras que con un parámetro de arreglo explícito debes construir y pasar un arreglo, sum(new int[]{1, 2, 3}). Un método varargs también acepta un arreglo directamente, así que es la opción más flexible.

Coddy programming languages illustration

Aprende a programar con Coddy

COMENZAR