Posso passare un array come argomento a un metodo con argomenti variabili in Java?

Mi piacerebbe essere in grado di creare una funzione come:

class A { private String extraVar; public String myFormat(String format, Object ... args){ return String.format(format, extraVar, args); } } 

Il problema qui è che args è trattato come Object[] nel metodo myFormat , e quindi è un singolo argomento per String.format , mentre vorrei che ogni singolo Object in args fosse passato come un nuovo argomento. Poiché String.format è anche un metodo con argomenti variabili, ciò dovrebbe essere ansible.

Se questo non è ansible, esiste un metodo come String.format(String format, Object[] args) ? In quel caso potrei extraVar ad extraVar usando un nuovo array e passarlo a quel metodo.

Il tipo sottostante di una function(Object... args) metodo variadica function(Object... args) è function(Object[] args) . Sun ha aggiunto vararg in questo modo per preservare la retrocompatibilità.

Quindi dovresti essere in grado di extraVar ad args e chiamare String.format(format, args) .

Sì, un T... è solo uno zucchero sintattico per un T[] .

JLS 8.4.1 Parametri di formato

L’ultimo parametro formale in una lista è speciale; può essere un parametro variabile di arità , indicato da un elipsis che segue il tipo.

Se l’ultimo parametro formale è un parametro arity variabile di tipo T , si considera che definisca un parametro formale di tipo T[] . Il metodo è quindi un metodo arity variabile . Altrimenti, è un metodo fisso . Le invocazioni di un metodo arity variabile possono contenere più espressioni di argomento effettive rispetto ai parametri formali. Verranno valutate tutte le espressioni di argomento reali che non corrispondono ai parametri formali che precedono il parametro arity della variabile e i risultati memorizzati in una matrice che verrà passata al richiamo del metodo.

Ecco un esempio per illustrare:

 public static String ezFormat(Object... args) { String format = new String(new char[args.length]) .replace("\0", "[ %s ]"); return String.format(format, args); } public static void main(String... args) { System.out.println(ezFormat("A", "B", "C")); // prints "[ A ][ B ][ C ]" } 

E sì, il metodo main sopra è valido, perché ancora una volta, String... è solo String[] . Inoltre, poiché gli array sono covarianti, una String[] è un Object[] , quindi puoi anche chiamare ezFormat(args) entrambi i casi.

Guarda anche

  • Guida linguistica Java / vararg

Varargs gotchas # 1: passing null

Il modo in cui i vararg sono risolti è piuttosto complicato e talvolta fa cose che potrebbero sorprenderti.

Considera questo esempio:

 static void count(Object... objs) { System.out.println(objs.length); } count(null, null, null); // prints "3" count(null, null); // prints "2" count(null); // throws java.lang.NullPointerException!!! 

A causa di come vengono risolti i vararg, l’ultima istruzione richiama con objs = null , che ovviamente causerebbe NullPointerException con objs.length . Se si desidera assegnare un argomento null a un parametro varargs, è ansible effettuare una delle seguenti operazioni:

 count(new Object[] { null }); // prints "1" count((Object) null); // prints "1" 

Domande correlate

Quello che segue è un esempio di alcune delle domande che le persone hanno posto quando si trattava di vararg:

  • bug con vararg e sovraccarico?
  • Come lavorare con varargs e reflection
  • Metodo più specifico con le corrispondenze sia di tipo fisso / variabile (vararg)

Vararg Gotchas # 2: aggiunta di argomenti aggiuntivi

Come hai scoperto, il seguente non “funziona”:

  String[] myArgs = { "A", "B", "C" }; System.out.println(ezFormat(myArgs, "Z")); // prints "[ [Ljava.lang.String;@13c5982 ][ Z ]" 

A causa del modo in cui funzionano i vararg, ezFormat riceve effettivamente 2 argomenti, il primo è una String[] , il secondo è una String . Se stai passando un array a varargs e vuoi che i suoi elementi vengano riconosciuti come singoli argomenti, e devi anche aggiungere un argomento in più, non hai altra scelta se non creare un altro array che ospita l’elemento extra.

Ecco alcuni utili metodi di supporto:

 static  T[] append(T[] arr, T lastElement) { final int N = arr.length; arr = java.util.Arrays.copyOf(arr, N+1); arr[N] = lastElement; return arr; } static  T[] prepend(T[] arr, T firstElement) { final int N = arr.length; arr = java.util.Arrays.copyOf(arr, N+1); System.arraycopy(arr, 0, arr, 1, N); arr[0] = firstElement; return arr; } 

Ora puoi fare quanto segue:

  String[] myArgs = { "A", "B", "C" }; System.out.println(ezFormat(append(myArgs, "Z"))); // prints "[ A ][ B ][ C ][ Z ]" System.out.println(ezFormat(prepend(myArgs, "Z"))); // prints "[ Z ][ A ][ B ][ C ]" 

Varargs gotchas # 3: passando una schiera di primitivi

Non “funziona”:

  int[] myNumbers = { 1, 2, 3 }; System.out.println(ezFormat(myNumbers)); // prints "[ [[email protected] ]" 

Varargs funziona solo con tipi di riferimento. Autoboxing non si applica alla matrice di primitivi. I seguenti lavori:

  Integer[] myNumbers = { 1, 2, 3 }; System.out.println(ezFormat(myNumbers)); // prints "[ 1 ][ 2 ][ 3 ]" 

Va bene passare un array – in effetti equivale alla stessa cosa

 String.format("%s %s", "hello", "world!"); 

equivale a

 String.format("%s %s", new Object[] { "hello", "world!"}); 

È solo zucchero sintattico – il compilatore converte il primo nel secondo, poiché il metodo sottostante si aspetta un array per il parametro vararg .

Vedere

  • Varargs – Documentazione J2SE 1.5

jasonmp85 ha ragione riguardo il passaggio di un diverso array a String.format . La dimensione di un array non può essere modificata una volta costruita, quindi dovrai passare un nuovo array invece di modificare quello esistente.

 Object newArgs = new Object[args.length+1]; System.arraycopy(args, 0, newArgs, 1, args.length); newArgs[0] = extraVar; String.format(format, extraVar, args); 

Stavo avendo lo stesso problema.

 String[] arr= new String[] { "A", "B", "C" }; Object obj = arr; 

E poi ha passato l’obj come argomento varargs. Ha funzionato.