Je suis en retard dans le jeu mais pour ce que ça vaut, je veux ajouter mes 2 cents. Ils vont à l'encontre de l' objectif de conception deOptional
, qui est bien résumé par la réponse de Stuart Marks , mais je suis toujours convaincu de leur validité (évidemment).
Utiliser partout en option
En général
J'ai écrit un article de blogOptional
complet sur l'utilisation, mais cela se résume à ceci:
- concevez vos classes pour éviter le caractère optionnel dans la mesure du possible
- dans tous les cas restants, la valeur par défaut devrait être d'utiliser
Optional
au lieu denull
- faire éventuellement des exceptions pour:
- variables locales
- renvoyer des valeurs et des arguments aux méthodes privées
- blocs de code critiques pour les performances (pas de suppositions, utilisez un profileur)
Les deux premières exceptions peuvent réduire le surcoût perçu des références d'emballage et de déballage dans Optional
. Ils sont choisis de telle sorte qu'un nul ne puisse jamais légalement passer une frontière d'une instance à une autre.
Notez que cela n'autorisera presque jamais Optional
s dans les collections, ce qui est presque aussi mauvais que null
s. Ne le fais pas. ;)
Concernant vos questions
- Oui.
- Si la surcharge n'est pas une option, oui.
- Si d'autres approches (sous-classement, décoration, ...) ne sont pas envisageables, oui.
- Je t'en prie, non!
Les avantages
Cela réduit la présence de null
s dans votre base de code, mais ne les supprime pas. Mais ce n'est même pas le point principal. Il existe d'autres avantages importants:
Clarifie l'intention
L'utilisation Optional
exprime clairement que la variable est, eh bien, facultative. Tout lecteur de votre code ou consommateur de votre API sera battu au-dessus de la tête par le fait qu'il pourrait ne rien y avoir et qu'un contrôle est nécessaire avant d'accéder à la valeur.
Supprime l'incertitude
Sans Optional
le sens d'un null
événement n'est pas clair. Il peut s'agir d'une représentation légale d'un état (voir Map.get
) ou d'une erreur d'implémentation comme une initialisation manquante ou échouée.
Cela change radicalement avec l'utilisation persistante de Optional
. Ici, déjà l'occurrence de null
signifie la présence d'un bug. (Parce que si la valeur avait été manquante, un Optional
aurait été utilisé.) Cela rend le débogage d'une exception de pointeur nul beaucoup plus facile car la question de la signification de cela null
est déjà résolue.
Plus de contrôles nuls
Maintenant que rien ne peut null
plus être , cela peut être appliqué partout. Que ce soit avec des annotations, des assertions ou des vérifications simples, vous n'avez jamais à vous demander si cet argument ou ce type de retour peut être nul. Ça ne peut pas!
Désavantages
Bien sûr, il n'y a pas de solution miracle ...
Performance
L'encapsulation de valeurs (en particulier les primitives) dans une instance supplémentaire peut dégrader les performances. Dans les boucles serrées, cela peut devenir perceptible, voire pire.
Notez que le compilateur peut être en mesure de contourner la référence supplémentaire pour les durées de vie de courte durée de Optional
s. En Java 10 , les types de valeurs peuvent réduire ou supprimer davantage la pénalité.
Sérialisation
Optional
n'est pas sérialisable mais une solution de contournement n'est pas trop compliquée.
Invariance
En raison de l'invariance des types génériques en Java, certaines opérations deviennent lourdes lorsque le type de valeur réel est poussé dans un argument de type générique. Un exemple est donné ici (voir "Polymorphisme paramétrique") .
Map<Character, String>
. S'il n'y a pas de substitution je peux utiliser ceci:Optional.ofNullable(map.get(c)).orElse(String.valueOf(c))
. Notez également que Facultatif a été volé à Guava et qu'il a une syntaxe beaucoup plus agréable:Optional.fromNullable(map.get(c)).or(String.valueOf(c));