Optional tipo introdujo en Java 8 es una cosa nueva para muchos de los desarrolladores.

Es un método getter regresar Optional<Foo> tipo en lugar de la clásica Foo una buena práctica? Suponga que el valor puede ser null.

  • Aunque es probable que atraer obstinado de respuestas, es una buena pregunta. Estoy mirando adelante a una respuesta con hechos reales sobre el tema.
  • La pregunta es si la nullablitity es inevitable. Un componente puede tener una propiedad que puede ser nulo, pero aún así, el programador utiliza dicho componente puede decidir guardar la más estricta que la propiedad nonull. Por lo que el programador no debería tener que lidiar con Optional entonces. O, en otras palabras, ¿null realmente representan la ausencia de un valor como el resultado de una búsqueda (donde Optional es apropiado) o es null sólo uno de los miembros del conjunto de valores posibles.
  • Véase también el debate sobre @NotNull anotaciones: stackoverflow.com/q/4963300/873282
InformationsquelleAutor leonprou | 2014-10-12

5 Comentarios

  1. 471

    Por supuesto, la gente va a hacer lo que ellos quieren. Pero sí tienen una clara intención cuando la adición de esta característica, y fue no ser de propósito general, tal vez tipo, tanto como a mucha gente le han gustado hacerlo. Nuestra intención es proporcionar una limitada mecanismo para el método de la biblioteca de tipos de retorno, donde no se necesita ser un camino claro para representar a los «sin resultado», y el uso de null para tal fue abrumadoramente probable que causen errores.

    Por ejemplo, usted probablemente nunca debe usar para algo que devuelve un conjunto de resultados, o una lista de resultados; en lugar de devolver un array vacío o de la lista. Casi nunca lo uso como un campo de algo o un parámetro de método.

    Creo que rutinariamente usando como valor de retorno para los captadores definitivamente sería una sobre-utilización.

    No hay nada mal con Opcional que debe ser evitado, simplemente no es lo que muchas personas desean, y en consecuencia estábamos bastante preocupados por el riesgo de celosos sobre-uso.

    (Anuncio de servicio público: NUNCA llamada Optional.get a menos que pueda demostrar que nunca será nulo; en lugar de utilizar uno de los métodos seguros como orElse o ifPresent. En retrospectiva, debería haber llamado get algo como getOrElseThrowNoSuchElementException o algo que la hizo mucho más claro que este fue un muy peligroso método que afectaba a todo el propósito de la Optional en el primer lugar. La lección aprendida. (ACTUALIZACIÓN: Java 10 ha Optional.orElseThrow(), que es semánticamente equivalente a get(), pero cuyo nombre es más apropiado.))

    • (Con respecto a la última parte) …y cuando tenemos la confianza de que el valor nunca es null podemos usar orElseThrow(AssertionError::new), ejem o orElseThrow(NullPointerException::new)
    • Lo has hecho de manera diferente si su intención había sido la de introducir un propósito general o tal vez Algún tipo? Hay una manera en que el Facultativo no se ajustan a la ley de uno, o es que la introducción de Opcionales todo una nueva API que haría es no-Java-ish?
    • Por «propósito general tipo», me refería a la construcción en el lenguaje del tipo de sistema, en lugar de proporcionar una biblioteca de clases que se aproxima a ella. (Algunos idiomas tienen tipos de T? (T o nulo) y T! (no aceptan valores null T)) Opcional es sólo una clase; no podemos hacer conversiones implícitas entre los Foo y Opcional<Foo> como pudimos tener con soporte de idioma.
    • Bueno, parece que la gente adoptó la más ampliamente de lo que quería. Por supuesto, uno podría escribir su propio Maybe objeto con bastante facilidad, pero el uso de una clase existente, que es la parte de java.util es aún más fácil. Bueno, al menos para su comodidad, no recuerdo nunca el uso de Optional.get. Estoy de acuerdo en que sería muy bueno para tenerlo como parte de un sistema de tipo.
    • Me he preguntado por un tiempo ¿por qué el énfasis en el mundo de Java era Opcional, y no mejor análisis estático. Opcional tiene algunas ventajas, pero la enorme ventaja de que null tiene compatibilidad hacia atrás; Map::get devuelve un aceptan valores null V, no un Optional<V>, y eso nunca va a cambiar. Podría fácilmente haber sido anotado @Nullable, aunque. Ahora tenemos que dos formas de expresar la falta de valor, además de menos incentivos para realmente obtener un análisis estático sucediendo, que parece como una peor posición.
    • Yo no tenía ni idea de que es como un retorno de valor para una propiedad que no era lo que y’all intención hasta que he leído esta respuesta aquí en StackOverflow. De hecho, llegué a creer que era exactamente lo que ustedes la intención de que después de leer este artículo sobre Oracle en el sitio web: oracle.com/technetwork/articles/java/… Gracias por aclarar
    • Honestamente, no veo ninguna tumba mejoras por este concepto : ( creo que habría sido más útil ser capaz de obtener un Objeto Vacío de cualquier tipo de referencia (por ejemplo, a través de un especial constructor). Se determinará un estado que claramente identifica el objeto como inútiles (por negativa IDs, etc). Así, en cualquier momento usted no puede encontrar un resultado, se obtiene el mismo no Válido/Inútil/Vacío Instancia de Objeto. Casi como vacío colecciones. Opcional<T> básicamente extractos de su null cheques en el código de la plantilla. Y al menos a mí, no nos vamos a Api aparece más clara cuando se utiliza anotaciones : (
    • Brian Goetz respuestas ‘¿hay cambios en java 8 que te arrepientes ahora?’ i.stack.imgur.com/LPg1Z.png Ver 16′:07″-17′:35″ de jaxenter.de/fragen-und-antworten-zu-java-8-qa-33108
    • Todavía no veo el argumento en contra de la devolución Opcional del captador de un miembro que acepta valores null campo. ¿Cómo es la sobre-utilizar en este caso?
    • La respuesta depende, en cierto grado, en la pregunta «¿qué es un getter» … existe una difusa línea entre «getter» y «método que devuelve algo.» Obviamente, no son útiles en casos de devolver un Opcional a partir de los métodos. Pero en el mundo real de código (para mejor o peor), la mayoría de los captadores (como el 99%) son sólo return x. En ese caso, devolver un Optional de un captador significa que usted está usando Optional como su representación del estado, y esto definitivamente no es lo que pretendía (y entra de lleno en el «celoso uso excesivo» de la categoría.)
    • Opcional está bien como propósito general tipo de aún si es una biblioteca de clase. De hecho, la mayoría de los idiomas con un propósito general tal vez/tipo de Opción que tienen es exactamente como un tipo de biblioteca (ver Haskell, Scala, ML, …), sin contar las versiones N para Java — aunque también tienen la coincidencia de patrones.
    • «usted debe probablemente nunca lo uso para algo que devuelve un conjunto de resultados, o una lista de resultados; en lugar de devolver un array vacío o de la lista» – en ninguna lista existente y una lista vacía tener diferentes significados semánticos, y por lo tanto no deben ser considerados de la misma. Por ejemplo, un getBooksOfUser(id de usuario id) método devuelve un valor vacío si el usuario no existe, sino devuelve una lista vacía si el usuario existe pero no tiene ningún libro; no es la misma cosa.
    • No entiendo esto. Quiero tal vez el tipo y Opcional es uno. ¿Por qué debo escribir mi propio, sólo porque se recomienda no para uso Opcional, como un campo?
    • Brian Goetz: Su respuesta original da algunos ejemplos de donde NO debemos usar opcional, pero ninguno donde deben ser utilizados. Usted podría ser capaz de hacer su punto más claramente si se da un ejemplo de donde Opcional valor de retorno es sin duda una buena manera de ir.
    • Opcional fue creado para la programación funcional, y que es donde se debe utilizar. he Aquí un buen ejemplo, cortesía de Brian Goetz. Fuera de la programación funcional, Opcional acaba de agregar complejidad al código, lo que hace que los fallos más probable. La gente lo está utilizando para evitar que se viera la palabra null en su código. Esto conduce a un código como este: si(Opcional.ofNullable(x).isPresent()) en lugar de if(x!=null). Yo me quedo con el uso de null.
    • Nope, «creado para la programación funcional» no es ni exacta ni útil declaración de intenciones.
    • Goetz desde entonces he moderado mi punto de vista, pero yo era probablemente reacción exagerada a una gran cantidad de muy mala utilización de Opcionales en mi último proyecto. Ahora puedo decir que los captadores debe devolver Opcional sólo cuando el valor de la realidad puede ser null. La sugerencia de que es la intención de «ayudar a mejorar el diseño de APIs» (desde la página de Oracle) ha llevado a la gente a poner Opcional en sus parámetros de entrada, y volviendo Opcional donde el valor nunca es nula. También he visto cómo su mal uso ha conducido a errores. También, su funcional-ejemplo de programación fue el único que me había encontrado donde Opcional fue muy útil.
    • Aquí están algunos ejemplos de los malos usos de los Opcionales, tomado del código de la producción.
    • ¿por qué es una mala práctica para el uso Opcional de un campo que puede tener ningún valor? Proporciona una capa adicional de información semántica en el tipo de nivel de sistema. Sin duda útil cuando se trabaja con el objeto de que usted no tiene que mirar todos los lugares en los que el campo para saber si él siempre tiene un valor o si se puede a veces no tienen ningún valor. Parece que el uso de un argumento de autoridad para justificar esta decisión, pero lo que necesitamos es una explicación.
    • Java8 parece haber orElseThrow así, ¿por qué lo dices Java 10 ahora tiene orElseThrow? (docs.oracle.com/javase/8/docs/api/java/util/…)
    • Java 8 solo tiene el Optional.orElseThrow versión que requiere un argumento, como en optional.orElseThrow(AssertionError::new). Pero Java 10 agregado de la no-argumento la versión de orElseThrow
    • Sé que soy muy tarde para este partido, pero hay un uso adicional de los Accesorios que más deberían estar familiarizados con el porque se usa en otros idiomas. El uso de un tipo Opcional le permite esencialmente definir un «tercer estado» que un campo puede tomar. Un estándar de java campo de objeto puede tener un valor o ser null. Con opcional, usted puede ahora representar a un tercer estado, es decir,undefined. Esto es útil para situaciones en las que null puede ser ambigua (es decir, null decir «este valor se ha omitido de la solicitud» o «este valor se debe establecer en null en el servidor»?).

  2. 69

    Después de hacer un poco de mi propia investigación, he llegado a través de un número de cosas que podrían sugerir que, cuando es apropiado. La más autorizada que la siguiente cita de un Oráculo artículo:

    «Es importante tener en cuenta que la intención de la clase Opcional es no para reemplazar cada referencia nula. En lugar de ello, su propósito es ayudar a diseñar más comprensible Api de modo que con sólo leer la firma de un método, usted puede decirle si usted puede esperar un valor opcional. Esto obliga a que activamente a desplegar una Opcional para lidiar con la ausencia de un valor».Cansado de Puntero Nulo Excepciones? Considere el Uso de Java SE 8 es Opcional!

    También encontré este fragmento de Java 8 Opcional: Cómo utilizar

    «Opcional no está destinado a ser utilizado en estos contextos, como no va a comprar nada:

    • en el modelo de dominio de la capa (no serializable)
    • en DTOs (misma razón)
    • en los parámetros de entrada de métodos
    • en los parámetros del constructor»

    Que también parece plantear algunos puntos válidos.

    Yo no era capaz de encontrar cualquier connotaciones negativas o banderas rojas para sugerir que Optional debe ser evitado. Creo que la idea general es que, si es útil o mejora la capacidad de uso de su API, lo utilizan.

    • stackoverflow.com/questions/25693309 – parece Jackson admite ya, por lo que «no serializable» ya no pasa como una razón válida 🙂
    • Sugiero que su respuesta frente a por qué el uso de Optional en los parámetros de entrada de métodos (más específicamente los constructores) «no comprar nada». dolszewski.com/java/java-8-optional-use-cases contiene una buena explicación.
    • He encontrado que alarmada opcional resultados que necesita ser transformada en otras Api requiere un parámetro Opcional. El resultado es bastante comprensible de la API. Consulte stackoverflow.com/a/31923105/105870
    • El enlace está roto. Podría usted por favor, actualice la respuesta?
    • Para añadir a esto. He creado un IntelliJ captador de plantilla para generar los captadores que volver Opcional<T> gist.github.com/suvodeep-pyne/4ec3a52b4b25d0026a98cf5d75d02c86
    • El problema es que a menudo no mejora la API, a pesar de las mejores intenciones de los desarrolladores. He sido colección de ejemplos de los malos usos de Opcional, todas tomadas de código de la producción, que usted puede comprobar hacia fuera.
    • No he leído tu enlace a fondo, pero creo que yo apoyo a la edición de esta respuesta con algunas referencias a esa información. Especialmente el último párrafo, que, en retrospectiva, no fue la mejor elección de palabras. Saludos 🙂
    • Lo siento, yo también acabo de dar cuenta que se ha hecho referencia a que la información en su propia respuesta. Yo upvoted hace algún tiempo. Aún así, esta respuesta podría utilizar alguna información actualizada y en general la mejora de la calidad. Me voy a apoyar en cualquier modificaciones pertinentes.
    • Lo siento para secuestrar un poco, pero su Rápida #1 parece estar desactivado – la verificación null es para propertyAsString, no para key.parse() resultado. Que parse() método no como null entradas.

  3. 19

    Yo diría que en general es una buena idea utilizar el tipo opcional para la devolución de los valores que se pueden aceptar valores null. Sin embargo, w.r.t. a marcos supongo que la sustitución de la clásica captadores con la opción de tipos de causar un montón de problemas cuando se trabaja con marcos (por ejemplo, Hibernate) que se basan en las convenciones de codificación para los getters y setters.

  4. 9

    La razón Optional fue añadido a Java es porque esta:

    return Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
        .stream()
        .filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
        .filter(m ->  Arrays.equals(m.getParameterTypes(), parameterClasses))
        .filter(m -> Objects.equals(m.getReturnType(), returnType))
        .findFirst()
        .getOrThrow(() -> new InternalError(...));

    es más que esto:

    Method matching =
        Arrays.asList(enclosingInfo.getEnclosingClass().getDeclaredMethods())
        .stream()
        .filter(m -> Objects.equals(m.getName(), enclosingInfo.getName())
        .filter(m ->  Arrays.equals(m.getParameterTypes(), parameterClasses))
        .filter(m -> Objects.equals(m.getReturnType(), returnType))
        .getFirst();
    if (matching == null)
      throw new InternalError("Enclosing method not found");
    return matching;

    Mi punto es que Opcional fue escrito para apoyar la programación funcional, que se añadió a Java al mismo tiempo. (El ejemplo que viene por cortesía de un blog de Brian Goetz. Un mejor ejemplo podría utilizar el orElse() método, ya que este código se generará una excepción de todos modos, pero usted consigue el cuadro.)

    Pero ahora, la gente está usando Opcional por una razón muy diferente. Lo están usando para la dirección de una falla en el diseño del lenguaje. El error es este: no Hay manera de especificar que de una API de parámetros y valores de retorno se les permite ser null. Puede ser mencionados en los javadocs, pero la mayoría de los desarrolladores ni siquiera escribir javadocs para su código, y no muchos se compruebe la javadocs como se escribe. Esto nos lleva a un montón de código que siempre busca valores nulos antes de usarlos, incluso a pesar de que a menudo no puede ser nulo porque ya estaban validados repetidamente nueve o diez veces la pila de llamadas.

    Creo que hubo una verdadera sed para resolver este error, porque muchas de las personas que vieron la nueva clase Opcional asumió su propósito fue aportar claridad a las APIs. Cual es la razón por la que la gente haga preguntas como «debería captadores de retorno Opcionales?» No, probablemente no, a menos que se espera que el getter para ser utilizado en la programación funcional, la cual es muy raro. De hecho, si nos fijamos en donde Opcional se utiliza en la API de Java, es sobre todo en la Secuencia de las clases, que son el núcleo de la programación funcional. (No he mirado muy a fondo, pero la Secuencia de clases podría ser el sólo lugar al que estamos acostumbrados.)

    Si piensas utilizar un captador en un poco de código funcional, podría ser una buena idea para tener un estándar de getter y un segundo que devuelve Opcional.

    Ah, y si usted necesita que su clase sea serializable, no debe absolutamente uso Opcional.

    Opcionales son una muy mala solución a la API falla porque: a) son muy detallado, y b) Que no fueron concebidas para resolver el problema en el primer lugar.

    Una solución mucho mejor para la API de error es de los Nullness Corrector. Esta es una anotación procesador que le permite especificar qué parámetros y valores de retorno se les permite ser nulo por proveyéndolos con @aceptan valores null. De esta manera, el compilador puede escanear el código y ver si un valor que en realidad puede ser null se pasa a un valor null no es permitido. Por defecto, se supone que nada se le permite ser nulo a menos que sea anotado así. De esta manera, usted no tiene que preocuparse acerca de los valores null. Pasa un valor null a un parámetro, el resultado será un error del compilador. Las pruebas de un objeto null que no puede ser null produce una advertencia del compilador. El efecto de esto es cambiar NullPointerException de un error en tiempo de ejecución a un error en tiempo de compilación.

    Esto lo cambia todo.

    Como para sus getters, no uso Opcional. Y tratamos de diseñar sus clases por lo que ninguno de los miembros puede ser null. Y tal vez trate de añadir la Nullness Corrector para su proyecto y declarar sus métodos getter y setter parámetros de @aceptan valores null si la necesitan. Yo sólo he hecho esto con nuevos proyectos. Probablemente produce una gran cantidad de advertencias en los proyectos existentes, escrito con mucho de superfluo pruebas null, por lo que podría ser difícil reconversión. Pero también se captura un montón de errores. Me encanta. Mi código es mucho más limpio y más fiable a causa de ella.

    (También hay un nuevo lenguaje que se ocupa de esto. Kotlin, que Java se compila a código de bytes, le permite especificar si un objeto puede ser nulo cuando se declara. Es un limpiador de enfoque).

    Addendum a la entrada Original (versión 2)

    Después de dar una gran cantidad de pensamiento, he de mala gana llegado a la conclusión de que es aceptable de retorno Opcional con una condición: Que el valor recuperado en realidad podría ser nulo. He visto un montón de código donde las personas de forma rutinaria el retorno Opcional a partir de los captadores que no puede devolver null. Yo lo veo como una muy mala práctica de codificación que sólo añade complejidad al código, lo que hace a los bichos más probable. Pero cuando el valor devuelto en realidad podría ser nulo, seguir adelante y ajustar dentro de un Facultativo.

    Tenga en cuenta que los métodos que están diseñados para la programación funcional, y que requieren de una referencia de función, es (y debe) ser escrito en dos formas, una de las cuales utiliza Opcional. Por ejemplo, Optional.map() y Optional.flatMap() tanto tomar referencias de función. En el primero se hace una referencia a un ordinario getter, y la segunda tiene que devuelve Opcional. Así que usted no hace a nadie un favor por el retorno Opcional donde el valor no puede ser nulo.

    Habiendo dicho todo esto, sigo sin ver el enfoque utilizado por el Nullness Corrector es la mejor manera de lidiar con valores nulos, ya que a su vez NullPointerExceptions de tiempo de ejecución errores de tiempo de compilación errores.

    • Esta respuesta parece más apropiado para mí. Opcional solo se añadió en java 8 cuando los arroyos se han añadido. Y sólo el flujo de retorno de funciones opcionales como lo que yo he visto.
    • Creo que este es uno de la mejor respuesta. La gente sabe lo que es Opcional y cómo funciona. Pero la parte más confusa es/fue donde a usar y cómo usarlo. por la lectura de este despeja muchas dudas.
  5. 3

    Si está utilizando modernas serializadores y otros marcos que entender Optional, a continuación, he encontrado estos directrices funcionan bien cuando la escritura Entity los frijoles y el dominio de las capas:

    1. Si la serialización de la capa (normalmente una DB) permite una null valor de una celda en la columna BAR en la tabla FOO, entonces la función de captador Foo.getBar() puede volver Optional que indica el desarrollador que este valor pueda ser razonablemente esperada para ser null y se debe manejar esto. Si la base de datos garantiza que el valor no va a ser nulo, a continuación, el captador debe no envolver esta en un Optional.
    2. Foo.bar debe ser private y no ser Optional. No hay realmente ninguna razón para que sea Optional si es private.
    3. El setter Foo.setBar(String bar) debe tomar el tipo de bar y no Optional. Si bien el uso de una null argumento, a continuación, el estado esta en el comentario de JavaDoc. Si es no ACEPTAR el uso de null un IllegalArgumentException o algún lógica de negocios es, en mi humilde opinión, más apropiado.
    4. Constructores no necesita Optional argumentos (por razones similares a la del punto 3). Por lo general sólo se incluyen los argumentos en el constructor que debe ser no nulo en la serialización de la base de datos.

    De hacer lo anterior más eficiente, deberías editar tu IDE de plantillas para la generación de captadores y las correspondientes plantillas para toString(), equals(Obj o) etc. o el uso de campos directamente para aquellos (la mayoría de IDE generadores de manejar con valores nulos).

Dejar respuesta

Please enter your comment!
Please enter your name here