Java Language
Wahlweise
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 bereitsOptional
ist. Wenn dies derflatMap
ist, wird es vonflatMap
nicht mit einem zusätzlichenOptional
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);