Suche…


Einführung

Optional ist ein Containerobjekt, das einen Wert ungleich Null enthalten kann oder nicht. Wenn ein Wert vorhanden ist, gibt isPresent() true und get() gibt den Wert zurück.

Es werden zusätzliche Methoden bereitgestellt, die vom Vorhandensein des enthaltenen Werts abhängen, z. B. orElse() , das einen Standardwert zurückgibt, wenn kein Wert vorhanden ist, und ifPresent() das einen Codeblock ausführt, wenn der Wert vorhanden ist.

Syntax

  • Optional.empty () // Erstellt eine leere optionale Instanz.
  • Optional.of (value) // Gibt ein Optional mit dem angegebenen Wert ungleich Null zurück. Eine NullPointerException wird ausgelöst, wenn der übergebene Wert null ist.
  • Optional.ofNullable (value) // Gibt ein Optional mit dem angegebenen Wert zurück, der null sein kann.

Gibt den Standardwert zurück, wenn optional leer ist

Verwenden Sie nicht nur Optional.get() da dies NoSuchElementException . Die Methoden Optional.orElse(T) und Optional.orElseGet(Supplier<? extends T>) bieten eine Möglichkeit, einen Standardwert anzugeben, falls das Optional leer ist.

String value = "something";

return Optional.ofNullable(value).orElse("defaultValue");
// returns "something"

return Optional.ofNullable(value).orElseGet(() -> getDefaultValue());
// returns "something" (never calls the getDefaultValue() method)
String value = null;

return Optional.ofNullable(value).orElse("defaultValue");
// returns "defaultValue"

return Optional.ofNullable(value).orElseGet(() -> getDefaultValue());
// calls getDefaultValue() and returns its results

Der entscheidende Unterschied zwischen orElse und orElseGet besteht darin, dass letztere nur ausgewertet wird, wenn das Optional leer ist, während das an den vorherigen gelieferte Argument ausgewertet wird, selbst wenn das Optional nicht leer ist. Die orElse sollte daher nur für Konstanten verwendet werden und niemals für die Bereitstellung von Werten, die auf irgendeiner Art von Berechnung basieren.

Karte

Verwenden Sie die map() Methode von Optional , um mit Werten zu arbeiten, die möglicherweise null ohne explizite null durchzuführen:

(Beachten Sie, dass die Operationen map() und filter() Gegensatz zu ihren Stream-Gegenstücken, die nur bei einer Terminal-Operation ausgewertet werden, sofort ausgewertet werden.)

Syntax:

public <U> Optional<U> map(Function<? super T,? extends U> mapper)

Code-Beispiele:

String value = null;

return Optional.ofNullable(value).map(String::toUpperCase).orElse("NONE");
// returns "NONE"
String value = "something";

return Optional.ofNullable(value).map(String::toUpperCase).orElse("NONE");
// returns "SOMETHING"

Da Optional.map () ein leeres optionales Element zurückgibt, wenn seine Zuordnungsfunktion NULL zurückgibt, können Sie mehrere map () - Vorgänge als eine Form der nullsicheren Dereferenzierung verketten. Dies wird auch als null-sichere Verkettung bezeichnet .

Betrachten Sie das folgende Beispiel:

String value = foo.getBar().getBaz().toString();

getBar , getBaz und toString können möglicherweise eine NullPointerException .

Eine alternative Methode zum Abrufen des Werts von toString() mithilfe von Optional :

String value = Optional.ofNullable(foo)
                       .map(Foo::getBar)
                       .map(Bar::getBaz)
                       .map(Baz::toString)
                       .orElse("");

Wenn eine der Zuordnungsfunktionen null zurückgibt, wird eine leere Zeichenfolge zurückgegeben.

Unten ist ein weiteres Beispiel, aber etwas anders. Der Wert wird nur gedruckt, wenn keine der Zuordnungsfunktionen null zurückgegeben hat.

Optional.ofNullable(foo)
        .map(Foo::getBar)
        .map(Bar::getBaz)
        .map(Baz::toString)
        .ifPresent(System.out::println);

Eine Ausnahme auslösen, wenn kein Wert vorhanden ist

Verwenden Sie die orElseThrow() -Methode von Optional , um den enthaltenen Wert orElseThrow() oder eine Ausnahme orElseThrow() , falls dies nicht festgelegt wurde. Dies ist ähnlich wie beim Aufruf von get() , nur dass beliebige Ausnahmetypen zulässig sind. Die Methode nimmt einen Lieferanten, der die Ausnahme zurückgeben muss, um ausgelöst zu werden.

Im ersten Beispiel gibt die Methode einfach den enthaltenen Wert zurück:

Optional optional = Optional.of("something");

return optional.orElseThrow(IllegalArgumentException::new);
// returns "something" string

Im zweiten Beispiel löst die Methode eine Ausnahme aus, da kein Wert festgelegt wurde:

Optional optional = Optional.empty();

return optional.orElseThrow(IllegalArgumentException::new);
// throws IllegalArgumentException

Sie können auch die Lambda-Syntax verwenden, wenn eine Ausnahme mit Nachricht ausgelöst werden soll:

optional.orElseThrow(() -> new IllegalArgumentException("Illegal"));

Filter

filter() wird verwendet, um anzuzeigen, dass Sie den Wert nur möchten, wenn er Ihrem Prädikat entspricht.

if (!somePredicate(x)) { x = null; } Sie sich das so vor, if (!somePredicate(x)) { x = null; } .

Code-Beispiele:

String value = null;
Optional.ofNullable(value) // nothing
        .filter(x -> x.equals("cool string"))// this is never run since value is null
        .isPresent(); // false
String value = "cool string";
Optional.ofNullable(value) // something
        .filter(x -> x.equals("cool string"))// this is run and passes
        .isPresent(); // true
String value = "hot string";
Optional.ofNullable(value) // something
        .filter(x -> x.equals("cool string"))// this is run and fails
        .isPresent(); // false

Verwendung von optionalen Containern für primitive Nummerntypen

OptionalDouble , OptionalInt und OptionalLong funktionieren wie Optional , sind jedoch speziell für das Umschließen von primitiven Typen konzipiert:

OptionalInt presentInt = OptionalInt.of(value);
OptionalInt absentInt = OptionalInt.empty();

Da numerische Typen einen Wert haben, gibt es keine spezielle Behandlung für Null. Leere Behälter können überprüft werden mit:

presentInt.isPresent(); // Is true.
absentInt.isPresent(); // Is false.

In ähnlicher Weise gibt es Kurzwörter, um das Wertemanagement zu unterstützen:

// Prints the value since it is provided on creation.
presentInt.ifPresent(System.out::println);

// Gives the other value as the original Optional is empty.
int finalValue = absentInt.orElseGet(this::otherValue);

// Will throw a NoSuchElementException.
int nonexistentValue = absentInt.getAsInt();

Führen Sie Code nur aus, wenn ein Wert vorhanden ist

Optional<String> optionalWithValue = Optional.of("foo");
optionalWithValue.ifPresent(System.out::println);//Prints "foo".

Optional<String> emptyOptional = Optional.empty();
emptyOptional.ifPresent(System.out::println);//Does nothing.

Geben Sie mit einem Lieferanten faul einen Standardwert an

Bei der normalen orElse Methode wird ein Object . Sie können sich also fragen, warum es hier eine Option gibt, einen Supplier orElseGet (die orElseGet Methode).

Erwägen:

String value = "something";
return Optional.ofNullable(value)
               .orElse(getValueThatIsHardToCalculate()); // returns "something"

Es würde immer noch getValueThatIsHardToCalculate() aufrufen, obwohl das Ergebnis nicht verwendet wird, da das optionale Element nicht leer ist.

Um diese Strafe zu vermeiden, liefern Sie einen Lieferanten:

String value = "something";
return Optional.ofNullable(value)
               .orElseGet(() -> getValueThatIsHardToCalculate()); // returns "something"

Auf diese Weise wird getValueThatIsHardToCalculate() nur aufgerufen, wenn die Optional leer ist.

FlatMap

flatMap ähnelt map . Der Unterschied wird vom Javadoc folgendermaßen beschrieben:

Diese Methode ähnelt der map(Function) , der bereitgestellte Mapper ist jedoch einer, dessen Ergebnis bereits Optional ist. Wenn dies der flatMap ist, wird es von flatMap nicht mit einem zusätzlichen Optional umbrochen.

Mit anderen Worten: Wenn Sie einen Methodenaufruf verketten, der ein Optional zurückgibt, können Sie mithilfe von Optional.flatMap das Erstellen verschachtelter Optionals vermeiden.

Zum Beispiel die folgenden Klassen gegeben:

public class Foo {
    Optional<Bar> getBar(){
        return Optional.of(new Bar());
    }
}

public class Bar {
}

Wenn Sie Optional.map , erhalten Sie ein verschachteltes Optional . dh Optional<Optional<Bar>> .

Optional<Optional<Bar>> nestedOptionalBar =
    Optional.of(new Foo())
        .map(Foo::getBar);

Wenn Sie jedoch Optional.flatMap , erhalten Sie ein einfaches Optional . dh Optional<Bar> .

Optional<Bar> optionalBar =
    Optional.of(new Foo())
        .flatMap(Foo::getBar);


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow