Optional – JAVA 8 – la fin des NPE

La fonctionnalité de Optional pour éviter les NPE.
Pierre LISERONMis à jour le 12 Avr 2015
optional-java.jpg

La fonctionnalité de Optional pour éviter les NPE.

Un peu dhistoire sur le NPE:

JAVA avait comme idée originale de supprimer la notion de pointeur (du moins de la masquer) afin de faciliter la vie des développeurs. Néanmoins pour des raisons de simplicité, la « valeur » null a été laissé. Et « à cause » de cette valeur null, a été créé la fameuse exception NullPointerException qui est lerreur à la fois la plus connue et la plus détestable car généralement on ne peut plus rien y faire

Problème avec le NullPointerException:

  • C’est une source d’erreur : la NPE est de loin l’erreur la plus fréquente en Java.
  • La NPE oblige à rajouter énormément de code pour tester si une variable n’est pas null.
  • Ça n’apporte rien au niveau sémantique.
  • C’est contre la philosophie Java qui souhaite masquer la notion de pointeur.

Quest-ce quun optional?

Un optional est une classe qui « wrappe » lobjet dont on a réellement besoin. Loptional encapsule dont lobjet métier et indique directement que cet objet est « facultatif » cest à dire quil peut être présent ou non. 

optional-java

Dans quel cas utiliser les Optional?

Le cas le plus évident est dans les classes métiers, celles qui portent les valeurs. Prenons un exemple dune commande. Dans une commande, il existe un objet client qui stocke les informations du client. Mais lors du processus de commande, cest objet client nexiste peut-être pas encore. Imaginons que nous soyons dans une commande web et que le client nest pas encore loggué. Avant les optionals, il était donc nécessaire de tester la nullité de lobjet client dans la classe commande presque à chaque utilisation, ce qui est très pénible. De plus, un développeur qui reprend le classe commande plus loin dans l’application, na aucun moyen de savoir (hormis la documentation) si le client va être présent dans la classe Commande. Pour pallier à ce problème, lutilisation de la classe Wrapper Optional répond à ce problème de la manière suivante:

Dans la classe Commande, au lieu de stocker lobjet Client, on stocke un Optional. Ceci indique directement que lobjet client peut être présent dans la classe ou peut être pas. Lavantage cest quen terme de visibilité, il devient facile de le comprendre. Sémantiquement cest un plus indiscutable.

Optional et utilisation

Premier exemple, ici on renseigne dans la classe commande un client qui est optional

public class Commande{
    private Optional<
Client> client = Optional.empty();
}

Il existe plusieurs manière de créer des optionals:

Optional<
DomainObject> opt = Optional.empty();
Optional<
DomainObject> opt = Optional.of(objet);
Optional<
DomainObject> opt = Optional.ofNullable(objet);

Pour récupérer la valeur, on peut utiliser la méthode map avec une référence de méthode. Lavantage des optionals, est lutilisation des methodes orElse ou orElseGet. Méthode orElse(T) permet de créer un objet si lobjet nexiste pas, comme une valeur par défaut sur un String.

La méthode orElseGet(Supplier) prend une lambda pour créer la valeur manquante. Ainsi, il nest plus possible de faire des NPE.

opt.map().orElse("Valeur par défaut")

On peut aussi récupérer la valeur par get() mais une erreur du type NoSuchElementException peut se produire si la valeur nest pas présente.

 Méthodes utilisables sur les optionals

<table>
  <tr>
    <th>
      Méthode
    </th>
    
    <th>
      Description
    </th>
  </tr>
  
  <tr>
    <td>
      orElse
    </td>
    
    <td>
      Fourni une valeur par défaut
    </td>
  </tr>
  
  <tr>
    <td>
      orElseGet<Supplier>
    </td>
    
    <td>
      Supplier appelé pour générer une valeur<br /> si besoin
    </td>
  </tr>
  
  <tr>
    <td>
      ifPresent(Consumer<? Super T>)
    </td>
    
    <td>
      Déclenche la consommation de l’élément<br /> si présent avec le lambda.
    </td>
  </tr>
</table>

Ainsi on se rend compte que les optionals permettent daméliorer la lecture du code JAVA. Néanmoins un reproche qui peut lui être fait est que les optionals sont assez verbeux à utiliser. Personnellement même si ils répondent au besoin, jaurai préférer lutilisation dun opérateur type ? qui aurait été plus facile à utiliser.