J'ai récemment lu à ce sujet et vu des gens utiliser cette classe, mais dans presque tous les cas, l'utilisation null
aurait également fonctionné - sinon plus intuitivement. Quelqu'un peut-il donner un exemple concret où Optional
réaliserait quelque chose qui null
ne pourrait pas ou d'une manière beaucoup plus propre? La seule chose à laquelle je peux penser est de l'utiliser avec Maps
qui n'accepte pas les null
clés, mais même cela pourrait être fait avec un côté "mapping" de la valeur de null. Quelqu'un peut-il me fournir un argument plus convaincant? Je vous remercie.
89
Réponses:
Membre de l'équipe Guava ici.
Le plus gros inconvénient
null
est probablement qu'il n'est pas évident de savoir ce que cela devrait signifier dans un contexte donné: il n'a pas de nom illustratif. Ce n'est pas toujours évident que celanull
signifie «aucune valeur pour ce paramètre» - diable, comme valeur de retour, parfois cela signifie «erreur», ou même «succès» (!!), ou simplement «la bonne réponse n'est rien».Optional
est souvent le concept que vous entendez réellement lorsque vous rendez une variable Nullable, mais pas toujours. Si ce n'est pas le cas, nous vous recommandons d'écrire votre propre classe, similaireOptional
mais avec un schéma de dénomination différent, pour clarifier ce que vous entendez réellement.Mais je dirais que le plus grand avantage de
Optional
n'est pas dans la lisibilité: l'avantage est sa preuve d'idiot. Cela vous oblige à réfléchir activement au cas absent si vous voulez que votre programme se compile du tout, car vous devez activement déballer le casOptional
et résoudre ce cas. Null permet d'oublier facilement des choses, et bien que FindBugs aide, je ne pense pas qu'il résout le problème aussi bien. Ceci est particulièrement pertinent lorsque vous renvoyez des valeurs qui peuvent ou non être "présentes". Vous (et d'autres) êtes beaucoup plus susceptibles d'oublier que celaother.method(a, b)
pourrait renvoyer unenull
valeur que vous ne l'oubliereza
probablementnull
lors de la mise en œuvreother.method
. RetourOptional
rend impossible pour les appelants d'oublier ce cas, car ils doivent déballer l'objet eux-mêmes.Pour ces raisons, nous vous recommandons d'utiliser
Optional
comme type de retour pour vos méthodes, mais pas nécessairement dans vos arguments de méthode.(Ceci est totalement cribbed, au fait, de la discussion ici .)
la source
Map
retournenull
si une clé n'est pas mappée, mais rappelez-vous que si vous le faitesmap.put(key, null)
, alorsmap.containsKey(key)
reviendratrue
maismap.get(key)
reviendranull
.Optional
peut être utile pour éclaircir la distinction entre le cas "explicitement mappé à nul" et le cas "absent de la carte". J'accorde que celaOptional
peut être abusé, mais je ne suis pas encore convaincu que le cas que vous décrivez est un abus.Optional<T>
est-ce que cette valeur est "trouvée, mais non valide". Ou plus précisément,Optional<T>
c'est un moyen de décorer n'importe quel typeT
avec une valeur supplémentaire "trouvé, mais non valide" - en créant un nouveau type en combinant deux types existants. Si vous avez une centaine de classes, il peut être compliqué de devoir créer une valeur distincte "trouvée, mais non valide" pour chacune, maisOptional<T>
peut facilement fonctionner pour toutes.Cela ressemble vraiment au
Maybe
modèle Monad de Haskell.Vous devriez lire ce qui suit, Wikipedia Monad (programmation fonctionnelle) :
Et lisez From Optional to Monad with Guava sur le blog de Kerflyn, qui traite de l'option facultative de Guava utilisée comme monade:
Edit: Avec Java8, il existe une option intégrée qui a des opérateurs monadiques comme
flatMap
. Cela a été un sujet controversé mais a finalement été mis en œuvre.Voir http://www.nurkiewicz.com/2013/08/optional-in-java-8-cheat-sheet.html
L'
flatMap
opérateur est essentiel pour permettre des opérations monadiques, et permet d'enchaîner facilement les appels qui renvoient tous des résultats optionnels.Pensez-y, si vous utilisiez l'
map
opérateur 5 fois, vous vous retrouveriez avec unOptional<Optional<Optional<Optional<Optional<String>>>>>
, tandis que l'utilisationflatMap
vous donneraitOptional<String>
Depuis Java8, je préférerais ne pas utiliser le Guava's Optional qui est moins puissant.
la source
Une bonne raison de l'utiliser est qu'il rend vos nulls très significatifs. Au lieu de renvoyer un null qui pourrait signifier beaucoup de choses (comme une erreur, un échec, ou vide, etc.), vous pouvez mettre un «nom» à votre null. Regardez cet exemple:
définissons un POJO de base:
}
Utilisons maintenant ce simple POJO:
Évitons maintenant d'utiliser null et faisons nos vérifications avec Optionnel pour que ce soit significatif
ainsi à la fin c'est un moyen de rendre les nulls significatifs, et moins d'ambiguïté.
la source
L'avantage le plus important de Optional est qu'il ajoute plus de détails au contrat entre l'implémenteur et l'appelant d'une fonction. Pour cette raison, il est à la fois utile pour les paramètres et le type de retour.
Si vous faites en sorte que la convention ait toujours
Optional
pour les objets nuls possibles, vous ajoutez plus de clarifications à des cas tels que:Optional<Integer> maxPrime(Optional<Integer> from, Optional<Integer> to)
Le contrat ici spécifie clairement qu'il y a une chance qu'un résultat ne soit pas renvoyé, mais montre également qu'il fonctionnera avec
from
etto
comme absent.Optional<Integer> maxPrime(Optional<Integer> from, Integer to)
Le contrat spécifie que le from est facultatif, donc une valeur absente peut avoir une signification spéciale comme commencer à partir de 2. Je peux m'attendre à ce qu'une valeur nulle pour le
to
paramètre lèvera une exception.Donc, la bonne partie de l'utilisation d'Optionnel est que le contrat est devenu à la fois descriptif (similaire avec
@NotNull
annotation) mais également formel puisque vous devez écrire du code.get()
pour y faire faceOptional
.la source