999 Stimmen

Wie verwende ich optionale Parameter in Java?

Welche Spezifikation unterstützt optionale Parameter?

1890voto

Vitalii Fedorenko Punkte 103468

Es gibt mehrere Möglichkeiten, optionale Parameter in Java zu simulieren:

  1. Ü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.

  1. 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.

  1. 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.

  1. 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.

  2. 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();
  3. 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.

588voto

laginimaineb Punkte 8115

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);
}

144voto

bhoot Punkte 1463

Mit Java 5.0 gibt es optionale Parameter. Deklarieren Sie Ihre Funktion einfach wie folgt:

public void doSomething(boolean... optionalFlag) {
    //default to "false"
    //boolean flag = (optionalFlag.length >= 1) ? optionalFlag[0] : false;
}

könnten Sie mit doSomething(); o doSomething(true); jetzt.

105voto

theninjagreg Punkte 1598

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.

77voto

Dario Punkte 47246

In Java gibt es keine optionalen Parameter. Was Sie tun können, ist, die Funktionen zu überladen und dann Standardwerte zu übergeben.

void SomeMethod(int age, String name) {
    //
}

// Overload
void SomeMethod(int age) {
    SomeMethod(age, "John Doe");
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X