Introduction
Optional, une classe introduite dans Java 8, est souvent mal utilisée. L’élimination des valeurs nulles n’est pas un objectif de Optional.
Le principal objectif de conception de Optional est d’être utilisé comme valeur de retour de la méthode de bibliothèque des fonctions lorsqu’une valeur de retour peut être absente. L’intention est que l’appelant vérifie immédiatement l’option et extraie la valeur réelle si elle est présente. Si la valeur est absente, l’appelant peut substituer une valeur par défaut ou lever une exception.
Cela se fait généralement en enchaînant des appels de méthodes à la fin d’un pipeline de flux (Stream Pipeline) qui renvoient des valeurs optionnelles.
Voyons où il ne faut pas utiliser la classe Optional.
Les endroits où il ne faut pas utiliser Optional
Évitez d’utiliser Optional dans les paramètres des méthodes :
Avec un paramètres Optional, vous passez de deux entrées possibles : null et not-null, à trois : null, non-null-sans-valeur, et non-null-avec-valeur.
Ajoutez à cela le fait que la surcharge est disponible depuis longtemps pour indiquer que certains paramètres sont facultatifs, et il n’y a vraiment aucune raison d’avoir des paramètres facultatifs.
Les outils d’analyse de code tels que SonarQube et IntelliJ signalent que les paramètres facultatifs dans les méthodes constituent le “code smell” (RSPEC-3553).
Puisque le point principal d’Optional est de fournir un moyen pour une fonction retournant une valeur d’indiquer l’absence d’une valeur de retour, cela permet à l’appelant de poursuivre une chaîne d’appels de méthodes.
Le passage d’un argument facultatif à une méthode pourrait fonctionner, mais c’est plutôt maladroit. Supposons que vous ayez une méthode qui prend une chaîne de caractères suivie d’une deuxième chaîne Optional.
Accepter une Optional comme deuxième argument donnerait un code comme celui-ci :
foo("bar", Optional.of("bae"));
foo("bar", Optional.empty());
Même accepter “null” est une meilleure chose :
foo("bar", "baz");
foo("bar", null);
Le mieux est probablement de disposer d’une méthode surchargée qui accepte un seul argument de type String et fournit une valeur par défaut pour le second :
foo("bar", "baz");
foo("bar");
Cette méthode a ses limites, mais elle est bien plus agréable que les deux précédentes.
Évitez d’utiliser Optional dans les champs (fields) :
Il n’est pas non plus recommandé d’utiliser Java Optional comme champ dans les POJO. Java Optional n’est pas sérialisable et si vous avez vraiment besoin d’un champ facultatif, vous pouvez utiliser des champs nullables avec un getter renvoyant Optional.
Évitez d’utiliser Optional dans les collections :
Parfois, les gens veulent mettre Optional dans des collections, comme List<Optional<X>> - Map<Key, Optional<Value>>
.
C’est généralement une mauvaise idée. Cela peut sembler nécessaire pour faire la distinction entre l’absence d’enregistrement et l’enregistrement null.
Il est souvent préférable de remplacer ces utilisations de Optional par des valeurs Null-Object (pas de véritables références nulles), ou simplement d’omettre complètement ces entrées de la collection.
Empreinte mémoire (Memory Footprint) :
Optional est une “box” et consomme 16 octets supplémentaires car elle ajoute également un niveau de redirection de référence, ce qui augmente potentiellement la pression sur le GC (Garbage Collector) et les “cache misses“.
Adaptation entre Null et Optional :
Parfois, il faut adapter du code utilisant Optional à du code qui veut null.
Si vous avez une référence nullable et que vous avez besoin d’un Optional :
Optional<T> opt = Optional.ofNullable(ref)
Si vous avez une Optional et que vous avez besoin d’une référence nullable :
opt.orElse(null)
Optional n’est pas “serializable” :
Java Optional n’est pas sérialisable par conception.
La classe Optional
en Java est utilisée pour représenter des valeurs qui peuvent ou non être présentes.
Cependant, elle n’implémente pas l’interface Serializable
, ce qui signifie qu’elle ne peut pas être sérialisée directement.
La classe Optional
en Java est utilisée pour représenter des valeurs qui peuvent ou non être présentes. Cependant, elle n’implémente pas l’interface Serializable
, ce qui signifie qu’elle ne peut pas être sérialisée directement.
Il y a plusieurs raisons pour lesquelles Optional
n’est pas sérialisable :
- La sérialisation de l’objet
Optional
peut entraîner des problèmes de performance et de mémoire, car elle doit stocker des informations supplémentaires pour indiquer si la valeur est présente ou absente. - L’interface
Serializable
est conçue pour sérialiser des objets qui ont des états.Optional
est un conteneur qui peut ou non contenir une valeur, il n’a donc pas d’état à sérialiser. - Il existe des alternatives plus efficaces pour la sérialisation des valeurs optionnelles, comme la sérialisation de la valeur elle-même s’il est présent ou la sérialisation d’un booléen qui indique si la valeur est présente ou absente.
Ping : Comment traiter les NullPointerException en Java