Introduction
En tant que développeur, nous sommes tous tombés sur des NullPointerException lors de l’écriture d’un code.
Pour éviter cela, il est nécessaire de mettre en place des contrôles de “nullité” avant d’accéder à la valeur d’un objet.

En outre, chaque objet peut contenir ou non une valeur. Si c’est le cas, sa valeur est stockée dans la mémoire et la variable que nous utilisons a une référence à cet objet. Si l’objet ne contient aucune valeur, celle-ci est remplacée par “null”, indiquant l’absence de valeur.
Pour traiter une NullPointerException d’une manière beaucoup plus propre, Java8 fournit une classe Optional.
Optional est essentiellement un objet “container” qui peut ou non contenir une valeur non-null. Il est conçu soit pour stocker une valeur, soit pour être “vide”. Il permet un contrôle implicite des valeurs nulles et un bon nombre d’API pour traiter les valeurs nulles, pour chaque objet représenté par un Optional. Cela signifie que le développeur n’est plus responsable de la vérification explicite des “nullités” qui seront prises en charge par la classe Optional.
Passons donc rapidement en revue les différentes API disponibles pour créer et accéder à Optional pour n’importe quel objet, nous allons utiliser cette classe “Product” pour exemple :
public class Product {
private String name;
private Seller seller;
}
Création d’Optional
1 – of() :
La première approche pour créer des Optional consiste à utiliser l’API .of()
, en passant une référence à un objet non-null : en cas de nullité, la méthode lève l’exception NullPointerException :
Product product = new Product();
Optional<Product> productOptional = Optional.of(product);
2 – ofNullable() :
Si le “product” est autorisé à être null, au lieu de l’API .of(), nous utiliserions la méthode .ofNullable()
. Elles ont les mêmes performances si la valeur est non nulle :
Product product = new Product();
Optional<Product> productOptional = Optional.ofNullable(product);
3 – Empty :
Et enfin, au lieu d’envelopper une variable de référence existante (null ou non-null), nous pouvons créer une valeur null dans le contexte d’un Optional. C’est un peu comme un conteneur vide qui renvoie une instance vide de Optional :
Optional<Product> productEmpty = Optional.empty();
Accès aux valeurs avec Optional
Il est temps d’accéder à la valeur de l’objet une fois que nous avons créé des Optional pour toute référence d’objet.
get() :
Avant d’accéder à la valeur à l’aide de l’API get()
, nous devons toujours vérifier que la valeur existe à l’aide de l’API isPresent()
, sinon, get()
lèvera une exception NoSuchElementException.
La fonction isPresent()
renvoie “true” si la valeur est présente, sinon false :
Product product = new Product();
Optional<Product> productOptional = Optional.ofNullable(product);
if (productOptional.isPresent() {
System.out.println(productOptional.get());
}
Une autre façon de vérifier la présence d’une valeur dans l’instance Optional est d’utiliser ifPresent()
comme indiqué ci-dessous. Dans ce scénario, la sortie sur le terminal sera vide car l’instance Optional est vide :
Optional<Product> productEmpty = Optional.empty();
productEmpty.ifPresent(product -> System.out.println(productOptional.get()));
orElse() || orElseGet() || orElseThrow ()
Si nous utilisons get()
avec un Optional vide, l’invocation de la méthode lancera une NoSuchElementException mais dans certains cas, au lieu de l’exception, nous voulons retourner la valeur par défaut.
En utilisant l’API orElse()
, nous pouvons y parvenir :
Product productDefault = new Product();
Optional<Product> productEmpty = Optional.empty();
System.out.println(productEmpty.orElse(productDefault));
Au lieu de fournir la valeur par défaut directement en tant qu’argument, en utilisant orElseGet()
nous pouvons utiliser une interface “supplier” et retourner le résultat si la valeur n’est pas présente avec Optional :
Optional<Product> productEmpty = Optional.empty();
System.out.println(productEmpty.orElseGet(() -> new Product()));
Au lieu de renvoyer une valeur alternative ou par défaut (comme nous l’avons vu dans l’exemple précédent), nous voulons parfois lever une exception, pour indiquer l’indisponibilité de la valeur à l’accesseur, ce qui peut être réalisé en utilisant orElseThrow()
:
Optional<Product> productEmpty = Optional.empty();
productEmpty.orElseThrow (new CustomException ("Product not found"));
Conclusion
La classe Optional s’accompagne de nombreuses API qui facilitent la vie.
Commencez donc à utiliser la classe Optional partout où vous le pouvez et évitez de résoudre les problèmes de NullPointerException inutiles.
Ping : Écrire un code lisible et facile à maintenir en Java