Sök…


Introduktion

Optional är ett behållareobjekt som kan innehålla ett värde som inte är noll eller inte. Om ett värde är närvarande kommer isPresent() att returnera true och get() kommer att returnera värdet.

Ytterligare metoder som beror på närvaron av det innehållande värdet tillhandahålls, till exempel orElse() , som returnerar ett standardvärde om värdet inte finns, och ifPresent() som kör ett kodblock om värdet är närvarande.

Syntax

  • Optional.empty () // Skapar en tom valfri instans.
  • Valfritt.of (värde) // Returnerar ett valfritt med det angivna icke-nullvärdet. En NullPointerException kastas om det överförda värdet är noll.
  • Valfritt.ofNullable (värde) // Returnerar ett valfritt med det angivna värdet som kan vara noll.

Returnera standardvärdet om valfritt är tomt

Använd inte bara Optional.get() eftersom det kan kasta NoSuchElementException . Optional.orElse(T) och Optional.orElseGet(Supplier<? extends T>) ger ett sätt att tillhandahålla ett standardvärde om valfritt är tomt.

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

Den avgörande skillnaden mellan orElse och orElseGet är att den senare utvärderas endast när valfritt är tomt medan argumentet som tillhandahålls till det tidigare utvärderas även om valfritt inte är tomt. orElse bör därför endast användas för konstanter och aldrig för att tillhandahålla värde baserat på någon slags beräkning.

Karta

Använd map() -metoden för Optional att arbeta med värden som kan vara null utan att göra explicita null :

(Observera att map() och filter() -operationerna utvärderas omedelbart, till skillnad från deras Stream-motsvarigheter som endast utvärderas vid en terminaloperation .)

Syntax:

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

Kodexempel:

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"

Eftersom Optional.map () returnerar ett tomt valfritt när dess mappningsfunktion returnerar noll kan du kedja flera kart () -operationer som en form av noll-säker dereferencing. Detta kallas också Null-safe chaining .

Tänk på följande exempel:

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

Vilket som helst av getBar , getBaz och toString kan potentiellt kasta en NullPointerException .

Här är ett alternativt sätt att få värdet från toString() med Optional :

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

Detta kommer att returnera en tom sträng om någon av mappningsfunktionerna returneras noll.

Nedan är ett annat exempel, men något annorlunda. Det kommer endast att skriva ut värdet om ingen av mappningsfunktionerna returnerade noll.

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

Kasta ett undantag om det inte finns något värde

Använd orElseThrow() som Optional att få det inneslutna värdet eller kasta ett undantag, om det inte har ställts in. Detta liknar att ringa get() förutom att det tillåter godtyckliga undantagstyper. Metoden tar en leverantör som måste returnera det undantag som ska kastas.

I det första exemplet returnerar metoden helt enkelt det innehållande värdet:

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

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

I det andra exemplet kastar metoden ett undantag eftersom ett värde inte har ställts in:

Optional optional = Optional.empty();

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

Du kan också använda lambda-syntaxen om det krävs ett undantag med meddelande:

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

Filtrera

filter() används för att indikera att du bara vill ha värdet om det stämmer med ditt predikat.

Tänk på det som if (!somePredicate(x)) { x = null; } .

Kodexempel:

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

Använda valfria behållare för primitiva numretyper

OptionalDouble , OptionalInt och OptionalLong fungerar som Optional , men är speciellt utformade för att linda in primitiva typer:

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

Eftersom numeriska typer har ett värde finns det ingen speciell hantering för noll. Tomma behållare kan kontrolleras med:

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

På liknande sätt finns det kortheter för att stödja värdeförvaltning:

// 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();

Kör bara koden om det finns ett värde närvarande

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.

Lazily tillhandahåller ett standardvärde med en leverantör

Den normala orElse metoden tar ett Object , så du kanske undrar varför det finns ett alternativ att tillhandahålla en Supplier här ( orElseGet metoden).

Överväga:

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

Det skulle fortfarande ringa getValueThatIsHardToCalculate() även om resultatet inte används eftersom tillvalet inte är tomt.

För att undvika denna straff levererar du en leverantör:

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

Detta sätt getValueThatIsHardToCalculate() kommer bara att ringas om Optional är tomt.

FlatMap

flatMap liknar map . Skillnaden beskrivs av javadoc enligt följande:

Den här metoden liknar map(Function) , men den medföljande kartläggaren är en vars resultat redan är ett Optional , och om det anropas, flatMap inte flatMap det med ett extra Optional .

Med andra ord, när du kedjan ett metodanrop att avkastningen ett Optional , med hjälp av Optional.flatMap undviker skapar kapslade Optionals .

Till exempel, med följande klasser:

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

public class Bar {
}

Om du använder Optional.map får du ett kapslat Optional ; dvs Optional<Optional<Bar>> .

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

Men om du använder Optional.flatMap får du ett enkelt Optional ; dvs Optional<Bar> .

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


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow