Guide To Java 8 Facultatif

Guide To Java 8 Facultatif

1. Vue d'ensemble

Dans ce didacticiel, nous allons montrer la classeOptional qui a été introduite dans Java 8.

Le but de la classe est de fournir une solution au niveau du type pour représenter des valeurs facultatives au lieu des référencesnull.

Pour mieux comprendre pourquoi nous devrions nous soucier de la classeOptional, jetez un œil àthe official Oracle’s article.

Lectures complémentaires:

Java facultatif comme type de retour

Découvrez les meilleures pratiques et le moment où renvoyer le type facultatif en Java.

Read more

Ajouts facultatifs à l'API Java 9

Exemples rapides et pratiques de nouvelles méthodes dans l'API facultative en Java.

Read more

2. Création d'objetsOptional

Il existe plusieurs manières de créer des objetsOptional. Pour créer un objetOptional vide, nous devons simplement utiliser sa méthode statiqueempty:

@Test
public void whenCreatesEmptyOptional_thenCorrect() {
    Optional empty = Optional.empty();
    assertFalse(empty.isPresent());
}

Notez que nous avons utilisé la méthodeisPresent() pour vérifier s'il y a une valeur à l'intérieur de l'objetOptional. Une valeur n'est présente que si nous avons crééOptional avec une valeur non -null. Nous examinerons la méthodeisPresent dans la section suivante.

On peut aussi créer un objetOptional avec la méthode statiqueof:

@Test
public void givenNonNull_whenCreatesNonNullable_thenCorrect() {
    String name = "example";
    Optional opt = Optional.of(name);
    assertTrue(opt.isPresent());
}

Cependant, l'argument passé à la méthodeof() ne peut pas êtrenull. Sinon, nous obtiendrons unNullPointerException:

@Test(expected = NullPointerException.class)
public void givenNull_whenThrowsErrorOnCreate_thenCorrect() {
    String name = null;
    Optional.of(name);
}

Mais, au cas où nous attendions des valeurs denull, nous pouvons utiliser la méthodeofNullable():

@Test
public void givenNonNull_whenCreatesNullable_thenCorrect() {
    String name = "example";
    Optional opt = Optional.ofNullable(name);
    assertTrue(optionalName.isPresent());
}

En faisant cela, si nous transmettons une référencenull, cela ne lève pas d'exception mais renvoie plutôt un objetOptional vide:

@Test
public void givenNull_whenCreatesNullable_thenCorrect() {
    String name = null;
    Optional opt = Optional.ofNullable(name);
    assertFalse(optionalName.isPresent());
}

3. Vérification de la présence de valeur:isPresent() etisEmpty()

Lorsque nous avons un objetOptional retourné par une méthode ou créé par nous, nous pouvons vérifier s'il y a une valeur dedans ou non avec la méthodeisPresent():

@Test
public void givenOptional_whenIsPresentWorks_thenCorrect() {
    Optional opt = Optional.of("example");
    assertTrue(opt.isPresent());

    opt = Optional.ofNullable(null);
    assertFalse(opt.isPresent());
}

Cette méthode renvoietrue si la valeur encapsulée n'est pasnull.

De plus, à partir de Java 11, nous pouvons faire le contraire avec la méthodeisEmpty :

@Test
public void givenAnEmptyOptional_thenIsEmptyBehavesAsExpected() {
    Optional opt = Optional.of("example");
    assertFalse(opt.isEmpty());

    opt = Optional.ofNullable(null);
    assertTrue(opt.isEmpty());
}

4. Action conditionnelle avecifPresent()

La méthodeifPresent() nous permet d’exécuter du code sur la valeur encapsulée si elle n’est pas -null. AvantOptional, nous ferions:

if(name != null) {
    System.out.println(name.length());
}

Ce code vérifie si la variable de nom estnull ou non avant de continuer à exécuter du code dessus. Cette approche est longue et ce n’est pas le seul problème, elle est également sujette à des erreurs.

En effet, de quoi nous garantir qu’après l’impression de cette variable, nous ne l’utiliserons plus, puisforget to perform the null check.

This can result in a NullPointerException at runtime if a null value finds its way into that code. Lorsqu'un programme échoue en raison de problèmes d'entrée, c'est souvent le résultat de mauvaises pratiques de programmation.

Optional nous oblige à traiter explicitement les valeurs Nullables comme un moyen d'appliquer de bonnes pratiques de programmation. Voyons maintenant comment le code ci-dessus pourrait être refactoré dans Java 8.

Dans un style de programmation fonctionnel typique, nous pouvons exécuter une action sur un objet réellement présent:

@Test
public void givenOptional_whenIfPresentWorks_thenCorrect() {
    Optional opt = Optional.of("example");
    opt.ifPresent(name -> System.out.println(name.length()));
}

Dans l'exemple ci-dessus, nous utilisons seulement deux lignes de code pour remplacer les cinq qui ont fonctionné dans le premier exemple. Une ligne pour envelopper l'objet dans un objetOptional et la suivante pour effectuer une validation implicite et exécuter le code.

5. Valeur par défaut avecorElse()

La méthodeorElse() est utilisée pour récupérer la valeur encapsulée dans une instanceOptional. Il prend un paramètre qui agit comme une valeur par défaut. La méthodeorElse() renvoie la valeur encapsulée si elle est présente et son argument dans le cas contraire:

@Test
public void whenOrElseWorks_thenCorrect() {
    String nullName = null;
    String name = Optional.ofNullable(nullName).orElse("john");
    assertEquals("john", name);
}

6. Valeur par défaut avecorElseGet()

La méthodeorElseGet() est similaire àorElse(). Cependant, au lieu de prendre une valeur à renvoyer si la valeurOptional n'est pas présente, il prend une interface fonctionnelle fournisseur qui est invoquée et renvoie la valeur de l'appel:

@Test
public void whenOrElseGetWorks_thenCorrect() {
    String nullName = null;
    String name = Optional.ofNullable(nullName).orElseGet(() -> "john");
    assertEquals("john", name);
}

7. Différence entreorElse etorElseGet()

Pour beaucoup de programmeurs qui sont nouveaux dansOptional ou Java 8, la différence entreorElse() etorElseGet() n'est pas claire. En fait, ces deux méthodes donnent l’impression qu’elles se chevauchent sur le plan de la fonctionnalité.

Cependant, il existe une différence subtile mais très importante entre les deux qui peut affecter considérablement les performances de notre code s'il n'est pas bien compris.

Créons une méthode appeléegetMyDefault() dans la classe de test qui ne prend aucun argument et renvoie une valeur par défaut:

public String getMyDefault() {
    System.out.println("Getting Default Value");
    return "Default Value";
}

Voyons deux tests et observons leurs effets secondaires pour établir à la fois oùorElse() etorElseGet() se chevauchent et où ils diffèrent:

@Test
public void whenOrElseGetAndOrElseOverlap_thenCorrect() {
    String text = null;

    String defaultText = Optional.ofNullable(text).orElseGet(this::getMyDefault);
    assertEquals("Default Value", defaultText);

    defaultText = Optional.ofNullable(text).orElse(getMyDefault());
    assertEquals("Default Value", defaultText);
}

Dans l'exemple ci-dessus, nous enveloppons un texte nul dans un objetOptional et nous essayons d'obtenir la valeur enveloppée en utilisant chacune des deux approches. L'effet secondaire est comme ci-dessous:

Getting default value...
Getting default value...

La méthodegetMyDefault() est appelée dans chaque cas. Il se trouve quewhen the wrapped value is not present, then both orElse() and orElseGet() work exactly the same way.

Maintenant, exécutons un autre test où la valeur est présente et idéalement, la valeur par défaut ne devrait même pas être créée:

@Test
public void whenOrElseGetAndOrElseDiffer_thenCorrect() {
    String text = "Text present";

    System.out.println("Using orElseGet:");
    String defaultText
      = Optional.ofNullable(text).orElseGet(this::getMyDefault);
    assertEquals("Text present", defaultText);

    System.out.println("Using orElse:");
    defaultText = Optional.ofNullable(text).orElse(getMyDefault());
    assertEquals("Text present", defaultText);
}

Dans l'exemple ci-dessus, nous n'enveloppons plus une valeurnull et le reste du code reste le même. Voyons maintenant les effets secondaires de l'exécution de ce code:

Using orElseGet:
Using orElse:
Getting default value...

Notez que lorsque vous utilisezorElseGet() pour récupérer la valeur encapsulée, la méthodegetMyDefault() n'est même pas appelée puisque la valeur contenue est présente.

Cependant, lors de l'utilisation deorElse(), que la valeur encapsulée soit présente ou non, l'objet par défaut est créé. Donc, dans ce cas, nous venons de créer un objet redondant qui n’est jamais utilisé.

Dans cet exemple simple, la création d'un objet par défaut ne présente pas de coût significatif, car la JVM sait comment s'y prendre. However, when a method such as getMyDefault() has to make a web service call or even query a database, then the cost becomes very obvious.

8. Exceptions avecorElseThrow()

La méthodeorElseThrow() découle deorElse() etorElseGet() et ajoute une nouvelle approche pour gérer une valeur absente. Au lieu de renvoyer une valeur par défaut lorsque la valeur encapsulée n'est pas présente, il lève une exception:

@Test(expected = IllegalArgumentException.class)
public void whenOrElseThrowWorks_thenCorrect() {
    String nullName = null;
    String name = Optional.ofNullable(nullName).orElseThrow(
      IllegalArgumentException::new);
}

Les références de méthodes dans Java 8 sont utiles ici, pour passer au constructeur d'exceptions.

9. Valeur renvoyée avecget()

La dernière approche pour récupérer la valeur encapsulée est la méthodeget():

@Test
public void givenOptional_whenGetsValue_thenCorrect() {
    Optional opt = Optional.of("example");
    String name = opt.get();
    assertEquals("example", name);
}

Cependant, contrairement aux trois approches ci-dessus,get() ne peut renvoyer une valeur que si l'objet encapsulé n'est pasnull, sinon, il lève une exception d'élément non:

@Test(expected = NoSuchElementException.class)
public void givenOptionalWithNull_whenGetThrowsException_thenCorrect() {
    Optional opt = Optional.ofNullable(null);
    String name = opt.get();
}

C'est le défaut majeur de la méthodeget(). Idéalement,Optional devrait nous aider à éviter de telles exceptions imprévues. Par conséquent, cette approche va à l'encontre des objectifs deOptional et sera probablement obsolète dans une prochaine version.

Il est donc conseillé d'utiliser les autres variantes qui nous permettent de préparer et de traiter explicitement le casnull.

10. Retour conditionnel avecfilter()

Nous pouvons exécuter un test en ligne sur notre valeur encapsulée avec la méthodefilter. Il prend un prédicat comme argument et renvoie un objetOptional. Si la valeur encapsulée passe le test du prédicat, alors leOptional est renvoyé tel quel.

Cependant, si le prédicat renvoiefalse, alors il renverra unOptional vide:

@Test
public void whenOptionalFilterWorks_thenCorrect() {
    Integer year = 2016;
    Optional yearOptional = Optional.of(year);
    boolean is2016 = yearOptional.filter(y -> y == 2016).isPresent();
    assertTrue(is2016);
    boolean is2017 = yearOptional.filter(y -> y == 2017).isPresent();
    assertFalse(is2017);
}

La méthodefilter est normalement utilisée de cette manière pour rejeter les valeurs encapsulées en fonction d'une règle prédéfinie. Nous pourrions l'utiliser pour rejeter un format de courrier électronique incorrect ou un mot de passe qui n'est pas assez fort.

Prenons un autre exemple significatif. Disons que nous voulons acheter un modem et que nous ne nous soucions que de son prix. Nous recevons des notifications push sur les prix des modems d'un site donné et les stockons dans des objets:

public class Modem {
    private Double price;

    public Modem(Double price) {
        this.price = price;
    }
    // standard getters and setters
}

Nous transmettons ensuite à ces objets un code dont le seul but est de vérifier si le prix du modem est compris dans notre budget.

Jetons maintenant un œil au code sansOptional:

public boolean priceIsInRange1(Modem modem) {
    boolean isInRange = false;

    if (modem != null && modem.getPrice() != null
      && (modem.getPrice() >= 10
        && modem.getPrice() <= 15)) {

        isInRange = true;
    }
    return isInRange;
}

Faites attention à la quantité de code que nous devons écrire pour y parvenir, en particulier dans la conditionif. La seule partie de la condition si essentielle à l'application est la dernière vérification de la fourchette de prix; le reste des contrôles est défensif:

@Test
public void whenFiltersWithoutOptional_thenCorrect() {
    assertTrue(priceIsInRange1(new Modem(10.0)));
    assertFalse(priceIsInRange1(new Modem(9.9)));
    assertFalse(priceIsInRange1(new Modem(null)));
    assertFalse(priceIsInRange1(new Modem(15.5)));
    assertFalse(priceIsInRange1(null));
}

En dehors de cela, il est possible d’oublier les vérifications nulles sur une longue journée sans avoir d’erreurs de compilation.

Regardons maintenant une variante avecOptional#filter:

public boolean priceIsInRange2(Modem modem2) {
     return Optional.ofNullable(modem2)
       .map(Modem::getPrice)
       .filter(p -> p >= 10)
       .filter(p -> p <= 15)
       .isPresent();
 }

The map call is simply used to transform a value to some other value. Gardez à l'esprit que cette opération ne modifie pas la valeur d'origine.

Dans notre cas, nous obtenons un objet prix de la classeModel. Nous examinerons la méthodemap() en détail dans la section suivante.

Tout d'abord, si un objetnull est passé à cette méthode, nous ne prévoyons aucun problème.

Deuxièmement, la seule logique que nous écrivons à l'intérieur de son corps est exactement ce que décrit le nom de la méthode, le contrôle de la fourchette de prix. Optional s'occupe du reste:

@Test
public void whenFiltersWithOptional_thenCorrect() {
    assertTrue(priceIsInRange2(new Modem(10.0)));
    assertFalse(priceIsInRange2(new Modem(9.9)));
    assertFalse(priceIsInRange2(new Modem(null)));
    assertFalse(priceIsInRange2(new Modem(15.5)));
    assertFalse(priceIsInRange2(null));
}

L’approche précédente promet de vérifier la fourchette de prix mais doit faire plus que cela pour se défendre contre sa fragilité inhérente. Par conséquent, nous pouvons utiliser la méthodefilter pour remplacer les instructionsif inutiles et rejeter les valeurs indésirables.

11. Transformer la valeur avecmap()

Dans la section précédente, nous avons examiné comment rejeter ou accepter une valeur basée sur un filtre. Nous pouvons utiliser une syntaxe similaire pour transformer la valeurOptional avec la méthodemap():

@Test
public void givenOptional_whenMapWorks_thenCorrect() {
    List companyNames = Arrays.asList(
      "paypal", "oracle", "", "microsoft", "", "apple");
    Optional> listOptional = Optional.of(companyNames);

    int size = listOptional
      .map(List::size)
      .orElse(0);
    assertEquals(6, size);
}

Dans cet exemple, nous enveloppons une liste de chaînes dans un objetOptional et utilisons sa méthodemap pour effectuer une action sur la liste contenue. L'action que nous effectuons consiste à récupérer la taille de la liste.

La méthodemap renvoie le résultat du calcul encapsulé dansOptional. Il faut alors appeler une méthode appropriée sur leOptional retourné pour récupérer sa valeur.

Notez que la méthodefilter effectue simplement une vérification de la valeur et renvoie unboolean. Par contre, la méthodemap prend la valeur existante, effectue un calcul en utilisant cette valeur et renvoie le résultat du calcul enveloppé dans un objetOptional:

@Test
public void givenOptional_whenMapWorks_thenCorrect2() {
    String name = "example";
    Optional nameOptional = Optional.of(name);

    int len = nameOptional
     .map(String::length)
     .orElse(0);
    assertEquals(8, len);
}

Nous pouvons enchaînermap etfilter ensemble pour faire quelque chose de plus puissant.

Supposons que nous voulions vérifier l'exactitude d'un mot de passe saisi par un utilisateur; nous pouvons nettoyer le mot de passe en utilisant une transformationmap et vérifier son exactitude en utilisant unfilter:

@Test
public void givenOptional_whenMapWorksWithFilter_thenCorrect() {
    String password = " password ";
    Optional passOpt = Optional.of(password);
    boolean correctPassword = passOpt.filter(
      pass -> pass.equals("password")).isPresent();
    assertFalse(correctPassword);

    correctPassword = passOpt
      .map(String::trim)
      .filter(pass -> pass.equals("password"))
      .isPresent();
    assertTrue(correctPassword);
}

Comme nous pouvons le constater, sans nettoyage préalable de l'entrée, celle-ci sera filtrée - mais les utilisateurs peuvent prendre pour acquis que les espaces de début et de fin constituent tous des entrées. Nous transformons donc un mot de passe sale en un mot de passe propre avec unmap avant de filtrer les mauvais.

12. Transformer la valeur avecflatMap()

Tout comme la méthodemap(), nous avons également la méthodeflatMap() comme alternative pour transformer les valeurs. La différence est quemap transforme les valeurs uniquement lorsqu'elles sont déballées alors queflatMap prend une valeur encapsulée et la déballe avant de la transformer.

Auparavant, nous avons créé des objets simplesString etInteger pour les encapsuler dans une instanceOptional. Cependant, fréquemment, nous recevrons ces objets d'un accesseur d'un objet complexe.

Pour avoir une idée plus claire de la différence, examinons un objetPerson qui prend les détails d'une personne, tels que son nom, son âge et un mot de passe:

public class Person {
    private String name;
    private int age;
    private String password;

    public Optional getName() {
        return Optional.ofNullable(name);
    }

    public Optional getAge() {
        return Optional.ofNullable(age);
    }

    public Optional getPassword() {
        return Optional.ofNullable(password);
    }

    // normal constructors and setters
}

Nous créons normalement un tel objet et l'enveloppons dans un objetOptional comme nous l'avons fait avec String. Alternativement, il peut nous être retourné par un autre appel de méthode:

Person person = new Person("john", 26);
Optional personOptional = Optional.of(person);

Notez maintenant que lorsque nous enveloppons un objetPerson, il contiendra des instancesOptional imbriquées:

@Test
public void givenOptional_whenFlatMapWorks_thenCorrect2() {
    Person person = new Person("john", 26);
    Optional personOptional = Optional.of(person);

    Optional> nameOptionalWrapper
      = personOptional.map(Person::getName);
    Optional nameOptional
      = nameOptionalWrapper.orElseThrow(IllegalArgumentException::new);
    String name1 = nameOptional.orElse("");
    assertEquals("john", name1);

    String name = personOptional
      .flatMap(Person::getName)
      .orElse("");
    assertEquals("john", name);
}

Ici, nous essayons de récupérer l'attribut name de l'objetPerson pour effectuer une assertion.

Notez comment nous y parvenons avec la méthodemap() dans la troisième instruction, puis remarquez comment nous faisons de même avec la méthodeflatMap() par la suite.

La référence de la méthodePerson::getName est similaire à l'appelString::trim que nous avons eu dans la section précédente pour nettoyer un mot de passe.

La seule différence est quegetName() renvoie unOptional plutôt qu'une chaîne comme le faisait l'opérationtrim(). Ceci, couplé au fait qu'une transformationmap enveloppe le résultat dans un objetOptional conduit à unOptional imbriqué.

Lors de l'utilisation de la méthodemap(), nous devons donc ajouter un appel supplémentaire pour récupérer la valeur avant d'utiliser la valeur transformée. De cette façon, le wrapperOptional sera supprimé. Cette opération est effectuée implicitement lors de l'utilisation deflatMap.

13. ChaînageOptionals dans Java 8

Parfois, nous pouvons avoir besoin d'obtenir le premier objetOptional non vide à partir d'un certain nombre deOptionals. Dans de tels cas, il serait très pratique d'utiliser une méthode commeorElseOptional(). Malheureusement, une telle opération n'est pas directement prise en charge dans Java 8.

Commençons par présenter quelques méthodes que nous utiliserons tout au long de cette section:

private Optional getEmpty() {
    return Optional.empty();
}

private Optional getHello() {
    return Optional.of("hello");
}

private Optional getBye() {
    return Optional.of("bye");
}

private Optional createOptional(String input) {
    if (input == null || "".equals(input) || "empty".equals(input)) {
        return Optional.empty();
    }
    return Optional.of(input);
}

Afin de chaîner plusieurs objetsOptional et obtenir le premier objet non vide en Java 8, nous pouvons utiliser l'APIStream:

@Test
public void givenThreeOptionals_whenChaining_thenFirstNonEmptyIsReturned() {
    Optional found = Stream.of(getEmpty(), getHello(), getBye())
      .filter(Optional::isPresent)
      .map(Optional::get)
      .findFirst();

    assertEquals(getHello(), found);
}

L'inconvénient de cette approche est que toutes nos méthodesget sont toujours exécutées, quel que soit l'endroit où unOptional non vide apparaît dans lesStream.

Si nous voulons évaluer paresseusement les méthodes passées àStream.of(), nous devons utiliser la référence de méthode et l'interfaceSupplier:

@Test
public void givenThreeOptionals_whenChaining_thenFirstNonEmptyIsReturnedAndRestNotEvaluated() {
    Optional found =
      Stream.>>of(this::getEmpty, this::getHello, this::getBye)
        .map(Supplier::get)
        .filter(Optional::isPresent)
        .map(Optional::get)
        .findFirst();

    assertEquals(getHello(), found);
}

Si nous devons utiliser des méthodes qui prennent des arguments, nous devons recourir aux expressions lambda:

@Test
public void givenTwoOptionalsReturnedByOneArgMethod_whenChaining_thenFirstNonEmptyIsReturned() {
    Optional found = Stream.>>of(
      () -> createOptional("empty"),
      () -> createOptional("hello")
    )
      .map(Supplier::get)
      .filter(Optional::isPresent)
      .map(Optional::get)
      .findFirst();

    assertEquals(createOptional("hello"), found);
}

Souvent, nous voulons renvoyer une valeur par défaut au cas où tous lesOptional chaînés sont vides. Nous pouvons le faire simplement en ajoutant un appel àorElse() ouorElseGet() comme dans l'exemple suivant:

@Test
public void givenTwoEmptyOptionals_whenChaining_thenDefaultIsReturned() {
    String found = Stream.>>of(
      () -> createOptional("empty"),
      () -> createOptional("empty")
    )
      .map(Supplier::get)
      .filter(Optional::isPresent)
      .map(Optional::get)
      .findFirst()
      .orElseGet(() -> "default");

    assertEquals("default", found);
}

14. API du JDK 9Optional

La version de Java 9 a ajouté encore plus de nouvelles méthodes à l'APIOptional:

  • la méthodeor() pour fournir un fournisseur qui crée une alternativeOptional

  • la méthodeifPresentOrElse() qui permet d'exécuter une action si leOptional est présent ou une autre action sinon

  • Méthodestream() pour convertir unOptional enStream

Voici l'article complet pourfurther reading.

15. Mauvaise utilisation deOptionals

Enfin, voyons un moyen tentant, mais dangereux, d’utiliserOptionals: passer un paramètreOptional à une méthode.

Imaginons que nous ayons une liste dePerson et que nous voulions une méthode pour rechercher dans cette liste les personnes ayant un nom donné. Nous souhaitons également que cette méthode corresponde aux entrées d'au moins un certain âge, si elle est spécifiée. Ce paramètre étant optionnel, nous venons avec cette méthode:

public List search(List people, String name, Optional age) {
    // Null checks for people and name
    people.stream()
      .filter(p -> p.getName().equals(name))
      .filter(p -> p.getAge() >= age.orElse(0))
      .collect(Collectors.toList());
}

Ensuite, nous publions notre méthode et un autre développeur essaie de l’utiliser:

someObject.search(people, "Peter", null);

Maintenant, le développeur exécute son code et obtient unNullPointerException.There we are, having to null check our optional parameter, which defeats our initial purpose in wanting to avoid this kind of situation.

Voici quelques possibilités que nous aurions pu faire pour mieux le gérer:

public List search(List people, String name, Integer age) {
    // Null checks for people and name

    age = age != null ? age : 0;
    people.stream()
      .filter(p -> p.getName().equals(name))
      .filter(p -> p.getAge() >= age)
      .collect(Collectors.toList());
}

Là, le paramètre est toujours facultatif, mais nous le traitons en une seule vérification. Une autre possibilité aurait été decreate two overloaded methods:

public List search(List people, String name) {
    return doSearch(people, name, 0);
}

public List search(List people, String name, int age) {
    return doSearch(people, name, age);
}

private List doSearch(List people, String name, int age) {
    // Null checks for people and name
    return people.stream()
      .filter(p -> p.getName().equals(name))
      .filter(p -> p.getAge() >= age)
      .collect(Collectors.toList());
}

De cette manière, nous proposons une API claire avec deux méthodes qui font des choses différentes (bien qu’elles partagent la même implémentation).

Il existe donc des solutions pour éviter d'utiliserOptionals comme paramètres de méthode. The intent of Java when releasing Optional was to use it as a return type, indiquant ainsi qu'une méthode peut renvoyer une valeur vide. En fait, la pratique consistant à utiliserOptional comme paramètre de méthode est mêmediscouraged by some code inspectors.

16. Conclusion

Dans cet article, nous avons couvert la plupart des fonctionnalités importantes de la classe Java 8Optional.

Nous avons également brièvement exploré certaines raisons pour lesquelles nous choisirions d'utiliserOptional au lieu de la vérification explicite de null et de la validation d'entrée.

Nous avons également appris comment obtenir la valeur d'unOptional, ou une valeur par défaut si vide, avec les méthodesget(),orElse() etorElseGet() (et vuthe important difference between the two last ).

Ensuite, nous avons vu comment transformer ou filtrer nosOptionals avecmap(), flatMap() etfilter().

Nous avons vu ce qu'offre unAPIOptional fluent car il nous permet d'enchaîner facilement les différentes méthodes.

Enfin, nous avons vu comment utiliserOptionals comme paramètres de méthode est une mauvaise idée et comment l'éviter.

Le code source de tous les exemples de l'article est disponibleover on GitHub.