Recherche…


Introduction

Optional est un objet conteneur qui peut ou non contenir une valeur non nulle. Si une valeur est présente, isPresent() retournera true et get() retournera la valeur.

Des méthodes supplémentaires dépendant de la présence de la valeur contenue sont fournies, telles que orElse() , qui renvoie une valeur par défaut si value not present, et ifPresent() qui exécute un bloc de code si la valeur est présente.

Syntaxe

  • Optional.empty () // Crée une instance facultative vide.
  • Facultatif.of (valeur) // Renvoie une option avec la valeur non nulle spécifiée. Une exception NullPointerException sera lancée si la valeur transmise est nulle.
  • Facultatif.ofNullable (value) // Renvoie une option avec la valeur spécifiée pouvant être nulle.

Renvoie la valeur par défaut si Facultatif est vide

Ne vous contentez pas d'utiliser Optional.get() car cela peut NoSuchElementException . Les méthodes Optional.orElse(T) et Optional.orElseGet(Supplier<? extends T>) permettent de fournir une valeur par défaut dans le cas où l'option Facultatif est vide.

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 différence cruciale entre orElse et orElseGet fait que ce dernier n'est évalué que lorsque le orElseGet Optional est vide, tandis que l'argument fourni au précédent est évalué même si le paramètre Facultatif n'est pas vide. L' orElse ne doit donc être utilisé que pour les constantes et jamais pour fournir une valeur basée sur un calcul quelconque.

Carte

Utilisez la méthode map() de Optional pour travailler avec des valeurs pouvant être null sans effectuer de vérifications null explicites:

(Notez que les opérations map() et filter() sont évaluées immédiatement, contrairement à leurs homologues Stream qui ne sont évalués que lors d'une opération de terminal .)

Syntaxe:

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

Exemples de code:

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"

Etant donné que Optional.map () renvoie une valeur facultative vide lorsque sa fonction de mappage renvoie la valeur null, vous pouvez chaîner plusieurs opérations map () sous forme de déréférencement null-safe. Ceci est également connu sous le nom de chaînage Null-safe .

Prenons l'exemple suivant:

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

Tout ce qui getBar , getBaz et toString peut potentiellement lancer une NullPointerException .

Voici une autre manière d’obtenir la valeur de toString() utilisant Optional :

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

Cela renverra une chaîne vide si l'une des fonctions de mappage retourne null.

Voici un autre exemple, mais légèrement différent. Il imprimera la valeur uniquement si aucune des fonctions de mappage n'a renvoyé la valeur null.

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

Lancer une exception, s'il n'y a pas de valeur

Utilisez la méthode orElseThrow() de Optional pour obtenir la valeur contenue ou lancer une exception, si elle n'a pas été définie. Ceci est similaire à l'appel de get() , sauf qu'il permet des types d'exceptions arbitraires. La méthode prend un fournisseur qui doit renvoyer l'exception à lancer.

Dans le premier exemple, la méthode renvoie simplement la valeur contenue:

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

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

Dans le deuxième exemple, la méthode renvoie une exception car une valeur n'a pas été définie:

Optional optional = Optional.empty();

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

Vous pouvez également utiliser la syntaxe lambda si une exception avec un message est nécessaire:

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

Filtre

filter() est utilisé pour indiquer que vous souhaitez la valeur uniquement si elle correspond à votre prédicat.

Pensez-y comme if (!somePredicate(x)) { x = null; } .

Exemples de code:

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

Utilisation de conteneurs facultatifs pour les types de nombres primitifs

OptionalDouble , OptionalInt et OptionalLong fonctionnent comme Optional , mais sont spécifiquement conçus pour envelopper les types primitifs:

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

Comme les types numériques ont une valeur, il n'y a pas de traitement spécial pour null. Les conteneurs vides peuvent être vérifiés avec:

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

De même, des raccourcis existent pour faciliter la gestion de la valeur:

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

N'exécutez le code que s'il y a une valeur présente

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.

Fournissez une valeur par défaut en utilisant un fournisseur

La méthode orElse normale prend un Object , donc vous pourriez vous demander pourquoi il existe une option pour fournir un Supplier ici (la méthode orElseGet ).

Considérer:

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

Il appellerait toujours getValueThatIsHardToCalculate() même si son résultat n'est pas utilisé car l'option n'est pas vide.

Pour éviter cette pénalité, vous fournissez un fournisseur:

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

De cette manière, getValueThatIsHardToCalculate() sera uniquement appelé si le getValueThatIsHardToCalculate() Optional est vide.

FlatMap

flatMap est similaire à map . La différence est décrite par le javadoc comme suit:

Cette méthode est similaire à map(Function) , mais le mappeur fourni est un mappeur dont le résultat est déjà Optional . flatMap est flatMap , flatMap ne l'enveloppe pas avec un Optional supplémentaire.

En d'autres termes, lorsque vous enchaînez un appel de méthode qui renvoie un Optional , l'utilisation de Optional.flatMap évite de créer des options Optionals imbriquées.

Par exemple, compte tenu des classes suivantes:

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

public class Bar {
}

Si vous utilisez Optional.map , vous obtiendrez un Optional imbriqué; c'est-à-dire Optional<Optional<Bar>> .

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

Cependant, si vous utilisez Optional.flatMap , vous obtiendrez un simple Optional ; c'est-à-dire Optional<Bar> .

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


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow