Recientemente leí sobre esto y vi a personas que usaban esta clase, pero en casi todos los casos, el uso también nullhabría funcionado, si no de manera más intuitiva. ¿Alguien puede dar un ejemplo concreto donde Optionalse lograría algo que nullno se pudo o de una manera mucho más limpia? Lo único que se me ocurre es usarlo con Mapsque no acepte nullclaves, pero incluso eso se podría hacer con un "mapeo" lateral del valor nulo. ¿Alguien puede proporcionarme un argumento más convincente? Gracias.
89

Respuestas:
Miembro del equipo de guayaba aquí.
Probablemente la mayor desventaja
nulles que no es obvio lo que debería significar en un contexto dado: no tiene un nombre ilustrativo. No siempre es obvio quenullsignifica "sin valor para este parámetro"; diablos, como valor de retorno, a veces significa "error", o incluso "éxito" (!!), o simplemente "la respuesta correcta no es nada".Optionales con frecuencia el concepto al que se refiere cuando convierte una variable en anulable, pero no siempre. Cuando no lo sea, le recomendamos que escriba su propia clase, similar aOptionalpero con un esquema de nomenclatura diferente, para dejar en claro lo que realmente quiere decir.Pero yo diría que la mayor ventaja de
Optionalno es la legibilidad: la ventaja es que es a prueba de idiotas. Te obliga a pensar activamente en el caso ausente si quieres que tu programa se compile, ya que tienes que desenvolver activamenteOptionaly abordar ese caso. Null hace que sea inquietantemente fácil simplemente olvidar cosas, y aunque FindBugs ayuda, no creo que aborde el problema tan bien. Esto es especialmente relevante cuando devuelve valores que pueden estar "presentes" o no. Es mucho más probable que usted (y otros) olviden queother.method(a, b)podría devolver unnullvalor de lo que es probable que olvide queapodría sernullcuando esté implementandoother.method. RegresandoOptionalhace imposible que las personas que llaman olviden ese caso, ya que tienen que desenvolver el objeto ellos mismos.Por estas razones, le recomendamos que utilice
Optionalcomo tipo de retorno para sus métodos, pero no necesariamente en los argumentos de su método.(Por cierto, esto se basa totalmente en la discusión aquí ).
fuente
Mapregresanullsi una clave no está asignada, pero recuerde que si lo hacemap.put(key, null),map.containsKey(key)regresarátrueperomap.get(key)regresaránull.Optionalpuede ser útil para aclarar la distinción entre el caso "asignado explícitamente a nulo" y el caso "no presente en el mapa". Concedo queOptionalse puede abusar de eso , pero aún no estoy convencido de que el caso que describe sea un abuso.Optional<T>es ese valor "encontrado, pero no válido"? O más precisamente,Optional<T>es una forma de decorar cualquier tipoTcon un valor adicional "encontrado, pero no válido", creando un nuevo tipo combinando dos tipos existentes. Si tiene cien clases, puede resultar complicado tener que crear un valor "encontrado, pero no válido" para cada una, peroOptional<T>puede funcionar fácilmente para todas.Realmente se parece al
Maybepatrón Monad de Haskell.Debería leer lo siguiente, Wikipedia Monad (programación funcional) :
Y lea De Opcional a Mónada con guayaba en el Blog de Kerflyn, que trata sobre el Opcional de la guayaba utilizada como mónada:
Editar: Con Java8, hay un Opcional incorporado que tiene operadores monádicos como
flatMap. Este ha sido un tema controvertido pero finalmente se ha implementado.Ver http://www.nurkiewicz.com/2013/08/optional-in-java-8-cheat-sheet.html
El
flatMapoperador es esencial para permitir operaciones monádicas y permite encadenar fácilmente llamadas que devuelven resultados opcionales.Piénselo, si usara el
mapoperador 5 veces terminaría con unOptional<Optional<Optional<Optional<Optional<String>>>>>, mientras que usarloflatMaple daríaOptional<String>Desde Java8, prefiero no usar el Opcional de Guava, que es menos poderoso.
fuente
Una buena razón para usarlo es que hace que sus valores nulos sean muy significativos. En lugar de devolver un nulo que podría significar muchas cosas (como error, falla, vacío, etc.), puede poner un 'nombre' a su nulo. Mira este ejemplo:
definamos un POJO básico:
}
Ahora hagamos uso de este sencillo POJO:
Ahora evitemos el uso de nulo y hagamos nuestras comprobaciones con Opcional, por lo que es significativo
por lo tanto, al final, es una forma de hacer que los nulos sean significativos y menos ambiguos.
fuente
La ventaja más importante de Opcional es que agrega más detalles al contrato entre el implementador y el llamador de una función. Por esta razón, es útil tanto para los parámetros como para el tipo de retorno.
Si hace que la convención tenga siempre
Optionalpara posibles objetos nulos, agrega más aclaraciones a casos como:Optional<Integer> maxPrime(Optional<Integer> from, Optional<Integer> to)El contrato aquí especifica claramente que existe la posibilidad de que un resultado no se devuelva, pero también muestra que funcionará con
fromytocomo ausente.Optional<Integer> maxPrime(Optional<Integer> from, Integer to)El contrato especifica que from es opcional, por lo que un valor ausente puede tener un significado especial como comenzar desde 2. Puedo esperar que un valor nulo para el
toparámetro arroje una excepción.Entonces, lo bueno de usar Opcional es que el contrato se volvió tanto descriptivo (similar a la
@NotNullanotación) como formal, ya que debe escribir código.get()para hacer frenteOptional.fuente