Java Language
Optioneel
Zoeken…
Invoering
Optional
is een containerobject dat al dan niet een niet-nulwaarde kan bevatten. Als een waarde aanwezig is, isPresent()
true
en get()
retourneert de waarde.
Aanvullende methoden die afhankelijk zijn van de aanwezigheid van de ingesloten waarde, zoals orElse()
, die een standaardwaarde retourneert als waarde niet aanwezig is, en ifPresent()
die een codeblok uitvoert als de waarde aanwezig is.
Syntaxis
- Option.empty () // Maakt een lege optionele instantie.
- Optioneel.van (waarde) // Retourneert een Optioneel met de opgegeven niet-nulwaarde. Een NullPointerException wordt gegenereerd als de doorgegeven waarde nul is.
- Optioneel. VanNullable (waarde) // Retourneert een Optioneel met de opgegeven waarde die mogelijk null is.
Retourneer de standaardwaarde als Optioneel leeg is
Gebruik niet alleen Optional.get()
want dat kan NoSuchElementException
. De methoden Optional.orElse(T)
en Optional.orElseGet(Supplier<? extends T>)
bieden een manier om een standaardwaarde op te geven in het geval dat de optie Leeg is.
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
Het cruciale verschil tussen de orElse
en orElseGet
is dat de laatste alleen wordt geëvalueerd wanneer de Optioneel leeg is, terwijl het argument dat aan de vorige is gegeven wordt geëvalueerd, zelfs als de Optioneel niet leeg is. De orElse
mag daarom alleen worden gebruikt voor constanten en nooit voor het leveren van waarde op basis van enige vorm van berekening.
Kaart
Gebruik de methode map()
van Optional
om te werken met waarden die mogelijk null
zonder expliciete null
voeren:
(Houd er rekening mee dat de bewerkingen map()
en filter()
onmiddellijk worden geëvalueerd, in tegenstelling tot hun Stream-tegenhangers die alleen worden geëvalueerd bij een terminalbewerking .)
Syntaxis:
public <U> Optional<U> map(Function<? super T,? extends U> mapper)
Code voorbeelden:
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"
Omdat Option.map () een lege optie retourneert wanneer de toewijzingsfunctie null retourneert, kunt u verschillende map () -bewerkingen koppelen als een vorm van null-safe dereferencing. Dit wordt ook wel Null-safe chaining genoemd .
Overweeg het volgende voorbeeld:
String value = foo.getBar().getBaz().toString();
Elk van getBar
, getBaz
en toString
kan mogelijk een NullPointerException
.
Hier is een alternatieve manier om de waarde van toString()
met Optional
:
String value = Optional.ofNullable(foo)
.map(Foo::getBar)
.map(Bar::getBaz)
.map(Baz::toString)
.orElse("");
Dit retourneert een lege tekenreeks als een van de toewijzingsfuncties null heeft geretourneerd.
Hieronder is een ander voorbeeld, maar iets anders. De waarde wordt alleen afgedrukt als geen van de toewijzingsfuncties null heeft geretourneerd.
Optional.ofNullable(foo)
.map(Foo::getBar)
.map(Bar::getBaz)
.map(Baz::toString)
.ifPresent(System.out::println);
Gooi een uitzondering als er geen waarde is
Gebruik de methode orElseThrow()
van Optional
om de ingesloten waarde op te halen of een uitzondering te genereren, als deze niet is ingesteld. Dit is vergelijkbaar met het aanroepen van get()
, behalve dat het willekeurige uitzonderingstypen toestaat. Voor de methode is een leverancier nodig die de uitzondering moet teruggeven.
In het eerste voorbeeld retourneert de methode eenvoudig de ingesloten waarde:
Optional optional = Optional.of("something");
return optional.orElseThrow(IllegalArgumentException::new);
// returns "something" string
In het tweede voorbeeld genereert de methode een uitzondering omdat er geen waarde is ingesteld:
Optional optional = Optional.empty();
return optional.orElseThrow(IllegalArgumentException::new);
// throws IllegalArgumentException
U kunt ook de lambda-syntaxis gebruiken als een uitzondering met bericht moet worden weergegeven:
optional.orElseThrow(() -> new IllegalArgumentException("Illegal"));
Filter
filter()
wordt gebruikt om aan te geven dat u de waarde alleen wilt als deze overeenkomt met uw predikaat.
Zie het als if (!somePredicate(x)) { x = null; }
.
Code voorbeelden:
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
Optionele containers gebruiken voor primitieve nummertypen
OptionalDouble
, OptionalInt
en OptionalLong
werken zoals Optional
, maar zijn specifiek ontworpen om primitieve typen te verpakken:
OptionalInt presentInt = OptionalInt.of(value);
OptionalInt absentInt = OptionalInt.empty();
Omdat numerieke typen een waarde hebben, is er geen speciale afhandeling voor null. Lege containers kunnen worden gecontroleerd met:
presentInt.isPresent(); // Is true.
absentInt.isPresent(); // Is false.
Evenzo bestaan er steno's om waardebeheer te ondersteunen:
// 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();
Voer code alleen uit als er een waarde aanwezig is
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.
Geef een standaardwaarde op met behulp van een leverancier
De normale orElse
methode heeft een Object
, dus je kunt je afvragen waarom er een optie is om hier een Supplier
te leveren (de orElseGet
methode).
Overwegen:
String value = "something";
return Optional.ofNullable(value)
.orElse(getValueThatIsHardToCalculate()); // returns "something"
Het zou nog steeds getValueThatIsHardToCalculate()
aanroepen getValueThatIsHardToCalculate()
ook al wordt het resultaat niet gebruikt omdat de optionele optie niet leeg is.
Om deze boete te voorkomen, levert u een leverancier:
String value = "something";
return Optional.ofNullable(value)
.orElseGet(() -> getValueThatIsHardToCalculate()); // returns "something"
Op deze manier wordt getValueThatIsHardToCalculate()
alleen aangeroepen als de Optional
leeg is.
FlatMap
flatMap
is vergelijkbaar met map
. Het verschil wordt door de javadoc als volgt beschreven:
Deze methode is vergelijkbaar met
map(Function)
, maar de verstrekte mapper is er een waarvan het resultaat al eenOptional
, en indien aangeroepen,flatMap
het niet in met een extraOptional
.
Met andere woorden, wanneer u een methodeaanroep koppelt die een Optional
retourneert, wordt met Optional.flatMap
vermeden geneste Optionals
.
Bijvoorbeeld, gegeven de volgende klassen:
public class Foo {
Optional<Bar> getBar(){
return Optional.of(new Bar());
}
}
public class Bar {
}
Als u Optional.map
, krijgt u een genest Optional
; dwz Optional<Optional<Bar>>
.
Optional<Optional<Bar>> nestedOptionalBar =
Optional.of(new Foo())
.map(Foo::getBar);
Als u echter Optional.flatMap
, krijgt u een eenvoudige Optional
; dwz Optional<Bar>
.
Optional<Bar> optionalBar =
Optional.of(new Foo())
.flatMap(Foo::getBar);