Ho paura dei vararg. Non so per cosa usarli.
Inoltre, è pericoloso lasciare che le persone passino tutti gli argomenti che vogliono.
Qual è un esempio di un contesto che sarebbe un buon posto per usarli?
Ho paura dei vararg. Non so per cosa usarli.
Inoltre, è pericoloso lasciare che le persone passino tutti gli argomenti che vogliono.
Qual è un esempio di un contesto che sarebbe un buon posto per usarli?
Risposte:
I Vararg sono utili per qualsiasi metodo che deve affrontare un numero indeterminato di oggetti . Un buon esempio è String.format
. La stringa di formato può accettare qualsiasi numero di parametri, quindi è necessario un meccanismo per passare un numero qualsiasi di oggetti.
String.format("This is an integer: %d", myInt);
String.format("This is an integer: %d and a string: %s", myInt, myString);
Una buona regola empirica sarebbe:
"Usa varargs per qualsiasi metodo (o costruttore) che necessita di un array di T (qualunque sia il tipo T) come input".
Ciò renderà le chiamate a questi metodi più facili (non è necessario farlo new T[]{...}
).
È possibile estendere questa regola per includere metodi con un List<T>
argomento, a condizione che questo argomento sia solo per input (ovvero, l'elenco non viene modificato dal metodo).
Inoltre, mi asterrei dall'usarlo f(Object... args)
perché scivola verso un modo di programmazione con API poco chiare.
In termini di esempi, l'ho usato in DesignGridLayout , dove posso aggiungere diversi messaggi JComponent
in una chiamata:
layout.row().grid(new JLabel("Label")).add(field1, field2, field3);
Nel codice sopra il metodo add () è definito come add(JComponent... components)
.
Infine, l'implementazione di tali metodi deve tener conto del fatto che può essere chiamato con un vararg vuoto! Se vuoi imporre almeno un argomento, devi usare un brutto trucco come:
void f(T arg1, T... args) {...}
Considero questo trucco brutto perché l'implementazione del metodo sarà meno semplice che avere solo T... args
nella sua lista di argomenti.
Spero che questo aiuti a chiarire il punto su Varargs.
if (args.length == 0) throw new RuntimeException("foo");
? (Poiché il chiamante stava violando il contratto)
void f(T arg1, T... args)
questo assicura sempre che non venga mai chiamato senza alcun argomento, senza dover aspettare fino al runtime.
Uso varargs frequentemente per l'output nei registri ai fini del debug.
Praticamente ogni classe nella mia app ha un metodo debugPrint ():
private void debugPrint(Object... msg) {
for (Object item : msg) System.out.print(item);
System.out.println();
}
Quindi, all'interno dei metodi della classe, ho chiamate come le seguenti:
debugPrint("for assignment ", hwId, ", student ", studentId, ", question ",
serialNo, ", the grade is ", grade);
Quando sono soddisfatto che il mio codice funzioni, commento il codice nel metodo debugPrint () in modo che i log non contengano troppe informazioni estranee e indesiderate, ma posso lasciare le singole chiamate a debugPrint () senza commenti. In seguito, se trovo un bug, decomprimo il codice debugPrint () e tutte le mie chiamate a debugPrint () vengono riattivate.
Naturalmente, potrei altrettanto facilmente evitare varargs e invece fare quanto segue:
private void debugPrint(String msg) {
System.out.println(msg);
}
debugPrint("for assignment " + hwId + ", student " + studentId + ", question "
+ serialNo + ", the grade is " + grade);
Tuttavia, in questo caso, quando commento il codice debugPrint (), il server deve ancora affrontare il problema di concatenare tutte le variabili in ogni chiamata a debugPrint (), anche se non viene fatto nulla con la stringa risultante. Se uso varargs, tuttavia, il server deve solo inserirli in un array prima di rendersi conto di non averne bisogno. Molto tempo è risparmiato.
Varargs può essere usato quando non siamo sicuri del numero di argomenti da passare in un metodo. Crea una matrice di parametri di lunghezza non specificata in background e tale parametro può essere trattato come una matrice in fase di esecuzione.
Se abbiamo un metodo che è sovraccarico per accettare un numero diverso di parametri, quindi invece di sovraccaricare il metodo diverse volte, possiamo semplicemente usare il concetto di varargs.
Anche quando il tipo di parametri varierà, l'uso di "Test oggetto ..." semplifica molto il codice.
Per esempio:
public int calculate(int...list) {
int sum = 0;
for (int item : list) {
sum += item;
}
return sum;
}
Qui indirettamente un array di tipo int (elenco) viene passato come parametro e viene trattato come un array nel codice.
Per una migliore comprensione segui questo link (mi ha aiutato molto a capire chiaramente questo concetto): http://www.javadb.com/using-varargs-in-java
PS: Anche io avevo paura di usare Varargs quando non lo sapevo. Ma ora ci sono abituato. Come si dice: "Ci aggrappiamo al conosciuto, abbiamo paura dell'ignoto", quindi usalo il più possibile e anche tu inizierai a piacerti :)
Varargs è la funzione aggiunta in Java versione 1.5.
Perché usare questo?
Come funziona?
Crea una matrice con gli argomenti indicati e passa la matrice al metodo.
Esempio :
public class Solution {
public static void main(String[] args) {
add(5,7);
add(5,7,9);
}
public static void add(int... s){
System.out.println(s.length);
int sum=0;
for(int num:s)
sum=sum+num;
System.out.println("sum is "+sum );
}
}
Produzione :
2
la somma è 12
3
la somma è 21
Anch'io ho una paura legata a Varargs:
Se il chiamante passa in un array esplicito al metodo (al contrario di più parametri), riceverai un riferimento condiviso a quell'array.
Se è necessario archiviare questo array internamente, è consigliabile clonarlo prima per evitare che il chiamante sia in grado di modificarlo in seguito.
Object[] args = new Object[] { 1, 2, 3} ;
varArgMethod(args); // not varArgMethod(1,2,3);
args[2] = "something else"; // this could have unexpected side-effects
Anche se questo non è molto diverso dal passaggio in qualsiasi tipo di oggetto il cui stato potrebbe cambiare in seguito, poiché l'array è di solito (nel caso di una chiamata con più argomenti anziché un array) uno nuovo creato internamente dal compilatore che puoi tranquillamente usare, questo è certamente un comportamento inaspettato.
Uso varargs frequentemente per costruttori che possono prendere una sorta di oggetto filtro. Ad esempio, gran parte del nostro sistema basato su Hadoop si basa su un Mapper che gestisce la serializzazione e la deserializzazione degli articoli su JSON e applica un numero di processori che prendono ciascuno un elemento di contenuto e lo modificano e lo restituiscono oppure restituiscono null rifiutare.
Nel documento Java di Var-Args è abbastanza chiaro l'uso di var args:
http://docs.oracle.com/javase/1.5.0/docs/guide/language/varargs.html
sull'uso dice:
"Quindi, quando dovresti usare varargs? Come client, dovresti approfittarne ogni volta che l'API li offre. Gli usi importanti nelle API principali includono la riflessione, la formattazione dei messaggi e la nuova funzione printf. Come progettista API, dovresti usarli con parsimonia, solo quando il vantaggio è davvero convincente. In generale, non dovresti sovraccaricare un metodo varargs, o sarà difficile per i programmatori capire quale sovraccarico viene chiamato. "