Ich habe Angst vor Varargs. Ich weiß nicht, wofür ich sie verwenden soll.
Außerdem ist es gefährlich, die Leute so viele Argumente führen zu lassen, wie sie wollen.
Was ist ein Beispiel für einen Kontext, in dem sie gut verwendet werden können?
Ich habe Angst vor Varargs. Ich weiß nicht, wofür ich sie verwenden soll.
Außerdem ist es gefährlich, die Leute so viele Argumente führen zu lassen, wie sie wollen.
Was ist ein Beispiel für einen Kontext, in dem sie gut verwendet werden können?
Antworten:
Varargs sind nützlich für jede Methode, die mit einer unbestimmten Anzahl von Objekten umgehen muss . Ein gutes Beispiel ist String.format
. Die Formatzeichenfolge kann eine beliebige Anzahl von Parametern akzeptieren, sodass Sie einen Mechanismus benötigen, um eine beliebige Anzahl von Objekten zu übergeben.
String.format("This is an integer: %d", myInt);
String.format("This is an integer: %d and a string: %s", myInt, myString);
Eine gute Faustregel wäre:
"Verwenden Sie varargs für jede Methode (oder jeden Konstruktor), die ein Array von T (unabhängig vom Typ T) als Eingabe benötigt."
Dies erleichtert das Aufrufen dieser Methoden (dies ist nicht erforderlich) new T[]{...}
).
Sie können diese Regel erweitern, um Methoden mit einem List<T>
Argument einzuschließen, vorausgesetzt, dieses Argument dient nur zur Eingabe (dh die Liste wird von der Methode nicht geändert).
Außerdem würde ich auf die Verwendung verzichten f(Object... args)
da dies zu einer Programmiermethode mit unklaren APIs führt.
In Bezug auf Beispiele habe ich es in DesignGridLayout verwendet , wo ich mehrere JComponent
s in einem Aufruf hinzufügen kann :
layout.row().grid(new JLabel("Label")).add(field1, field2, field3);
Im obigen Code ist die add () -Methode definiert als add(JComponent... components)
.
Schließlich muss bei der Implementierung solcher Methoden berücksichtigt werden, dass sie mit einem leeren vararg aufgerufen werden können! Wenn Sie mindestens ein Argument vorbringen möchten, müssen Sie einen hässlichen Trick anwenden, wie z.
void f(T arg1, T... args) {...}
Ich halte diesen Trick für hässlich, da die Implementierung der Methode weniger einfach ist als nur T... args
in der Argumentliste.
Hoffentlich hilft dies dabei, den Punkt über Varargs zu klären.
if (args.length == 0) throw new RuntimeException("foo");
stattdessen eine Vorbedingungsprüfung hinzuzufügen ? (Da der Anrufer gegen den Vertrag verstieß)
void f(T arg1, T... args)
immer sicher, dass sie niemals ohne Argument aufgerufen wird, ohne bis zur Laufzeit warten zu müssen.
Ich verwende Varargs häufig für die Ausgabe in die Protokolle zum Zwecke des Debuggens.
So ziemlich jede Klasse in meiner App hat eine Methode debugPrint ():
private void debugPrint(Object... msg) {
for (Object item : msg) System.out.print(item);
System.out.println();
}
Dann habe ich innerhalb der Methoden der Klasse folgende Aufrufe:
debugPrint("for assignment ", hwId, ", student ", studentId, ", question ",
serialNo, ", the grade is ", grade);
Wenn ich zufrieden bin, dass mein Code funktioniert, kommentiere ich den Code in der debugPrint () -Methode aus, damit die Protokolle nicht zu viele irrelevante und unerwünschte Informationen enthalten, aber ich kann die einzelnen Aufrufe von debugPrint () unkommentiert lassen. Wenn ich später einen Fehler finde, kommentiere ich einfach den debugPrint () - Code aus und alle meine Aufrufe von debugPrint () werden reaktiviert.
Natürlich könnte ich genauso gut auf Varargs verzichten und stattdessen Folgendes tun:
private void debugPrint(String msg) {
System.out.println(msg);
}
debugPrint("for assignment " + hwId + ", student " + studentId + ", question "
+ serialNo + ", the grade is " + grade);
In diesem Fall muss der Server jedoch beim Auskommentieren des debugPrint () - Codes immer noch alle Variablen in jedem Aufruf von debugPrint () verketten, obwohl mit der resultierenden Zeichenfolge nichts unternommen wird. Wenn ich jedoch varargs verwende, muss der Server sie nur in ein Array einfügen, bevor er feststellt, dass er sie nicht benötigt. Es wird viel Zeit gespart.
Varargs können verwendet werden, wenn wir uns nicht sicher sind, wie viele Argumente in einer Methode übergeben werden sollen. Es erstellt ein Array von Parametern mit nicht angegebener Länge im Hintergrund, und ein solcher Parameter kann zur Laufzeit als Array behandelt werden.
Wenn wir eine Methode haben, die überladen ist, um eine unterschiedliche Anzahl von Parametern zu akzeptieren, können wir anstelle einer unterschiedlichen Überladung der Methode einfach das varargs-Konzept verwenden.
Auch wenn der Typ der Parameter variieren wird, vereinfacht die Verwendung von "Object ... test" den Code erheblich.
Beispielsweise:
public int calculate(int...list) {
int sum = 0;
for (int item : list) {
sum += item;
}
return sum;
}
Hier wird indirekt ein Array vom Typ int (Liste) als Parameter übergeben und im Code als Array behandelt.
Zum besseren Verständnis folgen Sie diesem Link (es hat mir sehr geholfen, dieses Konzept klar zu verstehen): http://www.javadb.com/using-varargs-in-java
PS: Sogar ich hatte Angst, Varargs zu verwenden, wenn ich es nicht wusste. Aber jetzt bin ich daran gewöhnt. Wie es heißt: "Wir klammern uns an das Bekannte, aus Angst vor dem Unbekannten", also benutze es einfach so oft du kannst und auch du wirst es mögen :)
Varargs ist die Funktion, die in Java Version 1.5 hinzugefügt wurde.
Warum das benutzen?
Wie funktioniert das?
Es erstellt ein Array mit den angegebenen Argumenten und übergibt das Array an die Methode.
Beispiel:
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 );
}
}
Ausgabe :
2
Summe ist 12
3
Summe ist 21
Ich habe auch eine Varargs-bezogene Angst:
Wenn der Aufrufer ein explizites Array an die Methode übergibt (im Gegensatz zu mehreren Parametern), erhalten Sie einen gemeinsamen Verweis auf dieses Array.
Wenn Sie dieses Array intern speichern müssen, möchten Sie es möglicherweise zuerst klonen, um zu verhindern, dass der Anrufer es später ändern kann.
Object[] args = new Object[] { 1, 2, 3} ;
varArgMethod(args); // not varArgMethod(1,2,3);
args[2] = "something else"; // this could have unexpected side-effects
Dies unterscheidet sich zwar nicht wirklich von der Übergabe eines Objekts, dessen Status sich später ändern könnte, da das Array normalerweise (bei einem Aufruf mit mehreren Argumenten anstelle eines Arrays) ein neues ist, das vom Compiler intern erstellt wurde und das Sie sicher erstellen können Verwenden Sie, dies ist sicherlich unerwartetes Verhalten.
Ich verwende varargs häufig für Konstruktoren, die eine Art Filterobjekt aufnehmen können. Beispielsweise basiert ein großer Teil unseres auf Hadoop basierenden Systems auf einem Mapper, der die Serialisierung und Deserialisierung von Elementen in JSON verwaltet und eine Reihe von Prozessoren anwendet, die jeweils ein Inhaltselement übernehmen und es entweder ändern und zurückgeben oder null zurückgeben ablehnen.
In Java doc von Var-Args ist die Verwendung von var args ziemlich klar:
http://docs.oracle.com/javase/1.5.0/docs/guide/language/varargs.html
Über die Nutzung heißt es:
"Wann sollten Sie also varargs verwenden? Als Client sollten Sie sie nutzen, wann immer die API sie anbietet. Wichtige Verwendungszwecke in Kern-APIs sind Reflexion, Nachrichtenformatierung und die neue printf-Funktion. Als API-Designer sollten Sie sie verwenden sparsam, nur wenn der Nutzen wirklich überzeugend ist. Im Allgemeinen sollten Sie eine varargs-Methode nicht überladen, da es sonst für Programmierer schwierig ist, herauszufinden, welche Überladung aufgerufen wird. "