Menu

Varargs in Java: metodi che accettano un numero qualsiasi di argomenti

Come i varargs (...) di Java permettono a un metodo di accettare un numero qualsiasi di argomenti, come diventano un array, la regola del varargs unico e finale, e le trappole della chiamata vuota e dell'ambiguità.

Questa pagina include editor eseguibili: modifica, esegui e vedi subito l'output.

Un metodo, un numero qualsiasi di argomenti

A volte non sai in anticipo di quanti argomenti ha bisogno un metodo. Potresti volere max(3, 9) in un momento e max(1, 7, 4, 2, 8) subito dopo. Senza varargs scriveresti un overload per ogni quantità oppure obbligheresti chi chiama a costruire un array. I varargs, abbreviazione di variable arguments (argomenti variabili), permettono a un solo metodo di accettare zero, uno o tanti valori dello stesso tipo.

Li dichiari mettendo tre puntini (...) dopo il tipo del parametro:

Chi chiama passa valori sciolti; dentro il metodo numbers è un vero array. Tutta l'idea è questa: il compilatore raccoglie per te gli argomenti in un array.

I varargs sono solo un array

A runtime non c'è nessuna magia. Un parametro dichiarato int... numbers è esattamente un int[] una volta dentro il metodo. Puoi chiederne la length, accedere agli indici e scorrerlo con un ciclo come qualsiasi altro array.

Proprio perché è davvero un array, puoi anche passare a un metodo varargs un array che hai già: accetta entrambe le forme:

Le regole: ultimo e unico

Due regole evitano ambiguità con i varargs, e il compilatore le fa rispettare entrambe:

  1. Il parametro varargs deve essere l'ultimo. Prima vengono i parametri normali, poi il parametro ... raccoglie tutto il resto.
  2. Un metodo può avere al massimo un parametro varargs. Con due sarebbe impossibile capire dove finisce uno e dove inizia l'altro.

Questo compila. Ma mettere i varargs per primi, static void log(Object... values, String level), è un errore di compilazione: varargs parameter must be the last. Il parametro obbligatorio level viene sempre prima del ....

Dove usi già i varargs

Hai sempre chiamato metodi varargs. System.out.printf e String.format sono gli esempi classici: il loro secondo parametro è Object... args:

Anche List.of(...), Arrays.asList(...) e molte API in stile builder usano i varargs. Ecco perché puoi passare loro un numero qualsiasi di elementi senza incapsulare niente in un array.

Varargs e overloading

Varargs e overloading interagiscono in un modo sorprendente. Quando sia un overload normale sia un overload varargs potrebbero corrispondere a una chiamata, Java preferisce quello più specifico: vince il metodo con un numero fisso di parametri:

pick(1, 2) corrisponde a entrambi, ma Java sceglie l'overload senza varargs perché è quello più adatto. Il metodo varargs viene eseguito solo quando nessun overload fisso corrisponde. Di solito è ciò che vuoi, ma significa che aggiungere un overload varargs può cambiare in silenzio il metodo scelto da una chiamata.

Attenzione alle chiamate vuote e a null

Due trappole colpiscono spesso. La prima: chiamare un metodo varargs senza argomenti gli passa un array vuoto, non null, quindi numbers.length vale 0 e il ciclo non fa niente. Non ti serve un controllo su null per il caso senza argomenti:

La seconda: passare un null letterale è ambiguo e pericoloso. Java può interpretare count(null) come "l'intero array varargs è null" invece che "un elemento null", e questo lancia una NullPointerException quando leggi la sua length. Se intendi davvero un singolo elemento null, sii esplicito con count((Object) null).

Prossima pagina: classi

I varargs completano ciò che puoi fare con i parametri dei metodi: liste di argomenti flessibili in aggiunta all'overloading. Finora i metodi sono rimasti sparsi in una classe con static. Ora vedrai come funzionano davvero le classi: raggruppare dati (campi) e comportamento (metodi) in tipi tutti tuoi, il cuore della programmazione a oggetti in Java.

Domande frequenti

Cosa sono i varargs in Java?

I varargs (argomenti variabili) permettono a un metodo di accettare un numero qualsiasi di argomenti dello stesso tipo. Li dichiari mettendo ... dopo il tipo: int sum(int... numbers). Chi chiama può passare zero, uno o tanti valori, e dentro il metodo numbers è un normale array. È zucchero sintattico: Java raccoglie per te gli argomenti sciolti in un array.

Un metodo Java può avere più di un parametro varargs?

No. Un metodo può avere al massimo un parametro varargs, e deve essere l'ultimo della lista dei parametri, per esempio void log(String level, Object... values). Se non fosse l'ultimo, Java non saprebbe dove finisce la parte di lunghezza variabile e dove inizia il parametro successivo. I parametri normali vengono sempre prima del parametro ....

Che differenza c'è tra varargs e un parametro array in Java?

A runtime sono quasi uguali: dentro il metodo un parametro varargs int... è un int[]. La differenza sta nella chiamata: con i varargs scrivi sum(1, 2, 3) (valori sciolti), mentre con un parametro array esplicito devi costruire e passare un array, sum(new int[]{1, 2, 3}). Un metodo varargs accetta anche direttamente un array, quindi è la scelta più flessibile.

Illustrazione dei linguaggi di programmazione di Coddy

Impara a programmare con Coddy

INIZIA