Ricerca…


introduzione

Optional è un oggetto contenitore che può contenere o meno un valore non nullo. Se è presente un valore, isPresent() restituirà true e get() restituirà il valore.

Vengono forniti ulteriori metodi che dipendono dalla presenza del valore contenuto, ad esempio orElse() , che restituisce un valore predefinito se value non è presente e ifPresent() che esegue un blocco di codice se il valore è presente.

Sintassi

  • Optional.empty () // Crea un'istanza opzionale vuota.
  • Optional.of (valore) // Restituisce un Facoltativo con il valore non null specificato. Una NullPointerException verrà lanciata se il valore passato è nullo.
  • Optional.ofNullable (valore) // Restituisce un Facoltativo con il valore specificato che può essere nullo.

Restituisce il valore predefinito se Opzionale è vuoto

Non utilizzare semplicemente Optional.get() poiché potrebbe generare NoSuchElementException . I metodi Optional.orElse(T) e Optional.orElseGet(Supplier<? extends T>) forniscono un modo per fornire un valore predefinito nel caso in cui l'opzione sia vuota.

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

La differenza cruciale tra orElse e orElseGet è che quest'ultimo viene valutato solo quando l'opzione è vuota mentre l'argomento fornito a quello precedente viene valutato anche se l'opzione non è vuota. orElse , orElse dovrebbe essere utilizzato solo per le costanti e mai per fornire valore basato su qualsiasi tipo di calcolo.

Carta geografica

Utilizza il metodo map() di Optional per lavorare con valori che potrebbero essere null senza fare controlli null espliciti:

(Si noti che le operazioni map() e filter() vengono valutate immediatamente, a differenza delle loro controparti Stream che vengono valutate solo su un'operazione terminale .)

Sintassi:

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

Esempi di codice:

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"

Poiché Optional.map () restituisce un opzionale vuoto quando la sua funzione di mappatura restituisce null, è possibile concatenare diverse operazioni map () come una forma di dereferenziazione null-safe. Questo è anche noto come concatenamento sicuro .

Considera il seguente esempio:

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

Qualsiasi getBar , getBaz e toString possono potenzialmente lanciare una NullPointerException .

Ecco un modo alternativo per ottenere il valore da toString() usando Optional :

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

Ciò restituirà una stringa vuota se una qualsiasi delle funzioni di mapping ha restituito null.

Di seguito è riportato un altro esempio, ma leggermente diverso. Stampa il valore solo se nessuna delle funzioni di mappatura ha restituito nulla.

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

Getta un'eccezione, se non c'è valore

Utilizzare il metodo orElseThrow() di Optional per ottenere il valore contenuto o generare un'eccezione, se non è stata impostata. È simile alla chiamata get() , tranne per il fatto che consente tipi di eccezioni arbitrarie. Il metodo accetta un fornitore che deve restituire l'eccezione da lanciare.

Nel primo esempio, il metodo restituisce semplicemente il valore contenuto:

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

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

Nel secondo esempio, il metodo genera un'eccezione perché non è stato impostato un valore:

Optional optional = Optional.empty();

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

È inoltre possibile utilizzare la sintassi lambda se è necessario lanciare un'eccezione con il messaggio:

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

Filtro

filter() viene utilizzato per indicare che si desidera il valore solo se corrisponde al proprio predicato.

Pensalo come if (!somePredicate(x)) { x = null; } .

Esempi di codice:

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

Utilizzo di contenitori opzionali per tipi di numeri primitivi

OptionalDouble , OptionalInt e OptionalLong funzionano come Optional , ma sono specificamente progettati per includere tipi primitivi:

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

Poiché i tipi numerici hanno un valore, non esiste una gestione speciale per null. I contenitori vuoti possono essere controllati con:

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

Allo stesso modo, esistono stenografie per aiutare la gestione del valore:

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

Esegui il codice solo se è presente un valore

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.

Fornisci un valore predefinito usando un fornitore

Il normale metodo orElse riceve un Object , quindi potresti chiedervi perché esiste un'opzione per fornire un Supplier qui (il metodo orElseGet ).

Tenere conto:

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

Chiamerebbe comunque getValueThatIsHardToCalculate() anche se il risultato non è utilizzato in quanto l'opzionale non è vuoto.

Per evitare questa penalità fornisci un fornitore:

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

In questo modo getValueThatIsHardToCalculate() verrà chiamato solo se l' Optional è vuota.

FlatMap

flatMap è simile alla map . La differenza è descritta da javadoc come segue:

Questo metodo è simile alla map(Function) , ma il mapper fornito è uno il cui risultato è già un Optional e, se invocato, flatMap non lo avvolge con un Optional .

In altre parole, quando si concatena una chiamata al metodo che restituisce un Optional , usando Optional.flatMap evita di creare Optionals nidificati.

Ad esempio, date le seguenti classi:

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

public class Bar {
}

Se usi Optional.map , otterrai un Optional nidificata; cioè Optional<Optional<Bar>> .

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

Tuttavia, se si utilizza Optional.flatMap , si otterrà un semplice Optional ; cioè Optional<Bar> .

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


Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow