Welche Spezifikation unterstützt optionale Parameter?
Antworten
Zu viele Anzeigen?Es gibt mehrere Möglichkeiten, optionale Parameter in Java zu simulieren:
-
Überladen von Methoden.
void foo(String a, Integer b) { //... }
void foo(String a) { foo(a, 0); // hier ist 0 ein Standardwert für b }
foo("a", 2); foo("a");
Eine der Einschränkungen dieses Ansatzes ist, dass er nicht funktioniert, wenn Sie zwei optionale Parameter desselben Typs haben und einer von ihnen weggelassen werden kann.
- Varargs.
a) Alle optionalen Parameter sind vom gleichen Typ:
void foo(String a, Integer... b) {
Integer b1 = b.length > 0 ? b[0] : 0;
Integer b2 = b.length > 1 ? b[1] : 0;
//...
}
foo("a");
foo("a", 1, 2);
b) Die Arten der optionalen Parameter können unterschiedlich sein:
void foo(String a, Object... b) {
Integer b1 = 0;
String b2 = "";
if (b.length > 0) {
if (!(b[0] instanceof Integer)) {
throw new IllegalArgumentException("...");
}
b1 = (Integer)b[0];
}
if (b.length > 1) {
if (!(b[1] instanceof String)) {
throw new IllegalArgumentException("...");
}
b2 = (String)b[1];
//...
}
//...
}
foo("a");
foo("a", 1);
foo("a", 1, "b2");
Der größte Nachteil dieses Ansatzes besteht darin, dass die statische Typüberprüfung verloren geht, wenn optionale Parameter von unterschiedlichem Typ sind. Wenn jeder Parameter eine andere Bedeutung hat, müssen Sie außerdem eine Möglichkeit haben, sie zu unterscheiden.
-
Nullen. Um die Einschränkungen der vorherigen Ansätze zu umgehen, können Sie Nullwerte zulassen und dann jeden Parameter in einem Methodenrumpf analysieren:
void foo(String a, Integer b, Integer c) { b = b != null ? b : 0; c = c != null ? c : 0; //... }
foo("a", null, 2);
Jetzt müssen alle Argumente angegeben werden, aber die Standardwerte können null sein.
-
Fakultativer Unterricht. Dieser Ansatz ähnelt den Nullen, verwendet aber die Java 8 Optional-Klasse für Parameter, die einen Standardwert haben:
void foo(String a, Optional bOpt) { Integer b = bOpt.isPresent() ? bOpt.get() : 0; //... }
foo("a", Optional.of(2)); foo("a", Optional.absent());
Optional macht einen Methodenvertrag für einen Aufrufer explizit, allerdings kann man eine solche Signatur zu langatmig finden.
Update: Java 8 enthält die Klasse
java.util.Optional
out-of-the-box, so dass es in Java 8 nicht notwendig ist, Guava aus diesem Grund zu verwenden. Der Name der Methode ist allerdings ein wenig anders. -
Muster des Erbauers. Das Builder-Muster wird für Konstruktoren verwendet und durch die Einführung einer eigenen Builder-Klasse implementiert:
class Foo { private final String a; private final Integer b; Foo(String a, Integer b) { this.a = a; this.b = b; } //... } class FooBuilder { private String a = ""; private Integer b = 0; FooBuilder setA(String a) { this.a = a; return this; } FooBuilder setB(Integer b) { this.b = b; return this; } Foo build() { return new Foo(a, b); } } Foo foo = new FooBuilder().setA("a").build();
-
Karten. Wenn die Anzahl der Parameter zu groß ist und für die meisten Standardwerte verwendet werden, können Sie die Methodenargumente als eine Karte ihrer Namen/Werte übergeben:
void foo(Map<String, Object> parameters) { String a = ""; Integer b = 0; if (parameters.containsKey("a")) { if (!(parameters.get("a") instanceof Integer)) { throw new IllegalArgumentException("..."); } a = (Integer)parameters.get("a"); } if (parameters.containsKey("b")) { //... } //... }
foo(ImmutableMap.<String, Object>of( "a", "a", "b", 2, "d", "value"));
In Java 9 ist dieser Ansatz einfacher geworden:
@SuppressWarnings("unchecked") static <T> T getParm(Map<String, Object> map, String key, T defaultValue) { return (map.containsKey(key)) ? (T) map.get(key) : defaultValue; } void foo(Map<String, Object> parameters) { String a = getParm(parameters, "a", ""); int b = getParm(parameters, "b", 0); // d = ... } foo(Map.of("a","a", "b",2, "d","value"));
Bitte beachten Sie, dass Sie jeden dieser Ansätze kombinieren können, um ein gewünschtes Ergebnis zu erzielen.
Varargs könnte das (in gewisser Weise) tun. Abgesehen davon müssen alle Variablen in der Deklaration der Methode angegeben werden. Wenn Sie möchten, dass eine Variable optional ist, können Sie die Methode mit einer Signatur überladen, die den Parameter nicht erfordert.
private boolean defaultOptionalFlagValue = true;
public void doSomething(boolean optionalFlag) {
...
}
public void doSomething() {
doSomething(defaultOptionalFlagValue);
}
Sie können etwas wie dieses verwenden:
public void addError(String path, String key, Object... params) {
}
Le site params
Variable ist optional. Sie wird wie ein löschbares Array von Objects behandelt.
Seltsamerweise konnte ich in der Dokumentation nichts darüber finden, aber es funktioniert!
Dies ist "neu" in Java 1.5 und höher (nicht unterstützt in Java 1.4 oder früher).
Ich sehe, dass der Benutzer bhoot dies ebenfalls unten erwähnt hat.
- See previous answers
- Weitere Antworten anzeigen