¿Por qué no debería usarse Java 8's Opcional en argumentos

392

He leído en muchos sitios web. Opcional debe usarse solo como tipo de retorno y no en argumentos de método. Estoy luchando por encontrar una razón lógica por la cual. Por ejemplo, tengo una lógica que tiene 2 parámetros opcionales. Por lo tanto, creo que tendría sentido escribir la firma de mi método de esta manera (solución 1):

public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {
    // my logic
}

Muchas páginas web especifican Opcional no deben usarse como argumentos de método. Con esto en mente, podría usar la siguiente firma del método y agregar un comentario claro de Javadoc para especificar que los argumentos pueden ser nulos, con la esperanza de que los futuros mantenedores lean el Javadoc y, por lo tanto, siempre realicen comprobaciones nulas antes de usar los argumentos (solución 2) :

public int calculateSomething(String p1, BigDecimal p2) {
    // my logic
}

Alternativamente, podría reemplazar mi método con cuatro métodos públicos para proporcionar una interfaz más agradable y hacer que sea más obvio que p1 y p2 son opcionales (solución 3):

public int calculateSomething() {
    calculateSomething(null, null);
}

public int calculateSomething(String p1) {
    calculateSomething(p1, null);
}

public int calculateSomething(BigDecimal p2) {
    calculateSomething(null, p2);
}

public int calculateSomething(String p1, BigDecimal p2) {
    // my logic
}

Ahora trato de escribir el código de la clase que invoca esta pieza lógica para cada enfoque. Primero recupero los dos parámetros de entrada de otro objeto que devuelve Optionalsy luego invoco calculateSomething. Por lo tanto, si se usa la solución 1, el código de llamada se vería así:

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1, p2);

si se usa la solución 2, el código de llamada se vería así:

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));

si se aplica la solución 3, podría usar el código anterior o podría usar lo siguiente (pero es significativamente más código):

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();
int result;
if (p1.isPresent()) {
    if (p2.isPresent()) {
        result = myObject.calculateSomething(p1, p2);
    } else {
        result = myObject.calculateSomething(p1);
    }
} else {
    if (p2.isPresent()) {
        result = myObject.calculateSomething(p2);
    } else {
        result = myObject.calculateSomething();
    }
}

Entonces mi pregunta es: ¿Por qué se considera una mala práctica usar Optionals como argumentos de método (ver solución 1)? Parece la solución más legible para mí y hace que sea más obvio que los parámetros podrían estar vacíos / nulos para futuros mantenedores. (Soy consciente de que los diseñadores Optionalpretendían que solo se usara como un tipo de retorno, pero no puedo encontrar ninguna razón lógica para no usarlo en este escenario).

Neil Stevens
fuente
16
Si usaras opcionales, ¿no tendrías que verificar que lo opcional pasado como parámetro no lo sea null?
biziclop
17
Sí, pero sería obvio para alguien más mantener el código en el futuro que el parámetro puede estar vacío / nulo, evitando potencialmente una excepción de puntero nulo en el futuro
Neil Stevens
1
Guau. ¿Se pasan argumentos nulos a un método? Eso es muy Visual Basic. ¿Qué principio está violando? SRP (tal vez). También viola otro principio cuyo nombre me deja desprovisto, siguiendo la línea de pasar SOLAMENTE la información necesaria para que un método o función haga su trabajo.
Luminoso
20
En teoría, todo lo que posiblemente sea nulo es como cualquier método en una biblioteca que posiblemente llame a System.exit (0). No puede verificar esto y no debe verificarlo. Todo lo que tendrías que hacer todo el tiempo que de hecho (casi) nunca deberías hacer. Como hacer que todos los parámetros sean finales. Deje que sus herramientas lo ayuden a evitar cambiar los valores de los parámetros u olvidarse de inicializar los campos en lugar de hacer que su código sea ilegible por miles de finales y tantas verificaciones nulas.
yeoman
66
En realidad, solo use las anotaciones no nulas / anulables, eso es lo que está buscando en esta situación, no opcional.
Bill K

Respuestas:

202

Oh, esos estilos de codificación deben tomarse con un poco de sal.

  1. (+) Pasar un resultado Opcional a otro método, sin ningún análisis semántico; dejando eso al método, está bastante bien.
  2. (-) El uso de parámetros opcionales que causan lógica condicional dentro de los métodos es literalmente contraproducente.
  3. (-) La necesidad de empaquetar un argumento en un Opcional, es subóptima para el compilador y realiza un ajuste innecesario.
  4. (-) En comparación con los parámetros anulables Opcional es más costoso.

En general: Opcional unifica dos estados, que tienen que ser desentrañados. Por lo tanto, es más adecuado para el resultado que la entrada, para la complejidad del flujo de datos.

Joop Eggen
fuente
38
En realidad, tener un Optionalparámetro representa uno de tres estados: un nullOpcional, un no nulo Optionalcon isPresent() == falsey un no nulo Optionalenvolviendo un valor real.
biziclop
16
@biziclop sí, un punto inevitable ya criticado. Pero la intención es tener solo expresiones no nulas. Que no tardó mucho, escuchar los consejos para evitar Opcional en algunos casos también, es bastante irónico. Una @NotNull Optional.
Joop Eggen
80
@biziclop Tenga en cuenta que si está utilizando Optional, el estado 1 ( nullOpcional) generalmente indica un error de programación, por lo que es mejor que no lo maneje (solo deje que arroje un NullPointerException)
user253751
50
"subóptimo para el compilador", "en comparación con los parámetros anulables Opcional es más costoso": estos argumentos podrían ser válidos para el lenguaje C y no para el lenguaje Java. Los programadores de Java deberían centrarse en código limpio, portabilidad, capacidad de prueba, buena arquitectura, modularidad, etc., y no en "Opcional es más costoso que la referencia nula". Y si descubres que necesitas concentrarte en las micro optimizaciones, será mejor que saltes objetos, listas, genéricos y cambies a matrices y primitivas (no quiero ofenderte aquí, solo estoy compartiendo mi opinión) .
Kacper86
15
"subóptimo para el compilador": la optimización prematura es la raíz de todo mal ... si no está escribiendo código crítico de rendimiento (que suele ser el caso cuando se trata de especificar una interfaz limpia), esto no debería ser una preocupación.
Mohan
165

La mejor publicación que he visto sobre el tema fue escrita por Daniel Olszewski :

Aunque podría ser tentador considerar Opcional para parámetros de método no obligatorios, tal solución palidece en comparación con otras posibles alternativas. Para ilustrar el problema, examine la siguiente declaración de constructor:

public SystemMessage(String title, String content, Optional<Attachment> attachment) {
    // assigning field values
}

A primera vista, puede parecer una decisión de diseño correcta. Después de todo, marcamos explícitamente el parámetro adjunto como opcional. Sin embargo, en cuanto a llamar al constructor, el código del cliente puede volverse un poco torpe.

SystemMessage withoutAttachment = new SystemMessage("title", "content", Optional.empty());
Attachment attachment = new Attachment();
SystemMessage withAttachment = new SystemMessage("title", "content", Optional.ofNullable(attachment));

En lugar de proporcionar claridad, los métodos de fábrica de la clase Opcional solo distraen al lector. Tenga en cuenta que solo hay un parámetro opcional, pero imagine tener dos o tres. El tío Bob definitivamente no estaría orgulloso de ese código 😉

Cuando un método puede aceptar parámetros opcionales, es preferible adoptar el enfoque bien probado y diseñar dicho caso utilizando la sobrecarga del método. En el ejemplo de la clase SystemMessage, declarar dos constructores separados es superior al uso de Opcional.

public SystemMessage(String title, String content) {
    this(title, content, null);
}

public SystemMessage(String title, String content, Attachment attachment) {
    // assigning field values
}

Ese cambio hace que el código del cliente sea mucho más simple y fácil de leer.

SystemMessage withoutAttachment = new SystemMessage("title", "content");
Attachment attachment = new Attachment();
SystemMessage withAttachment = new SystemMessage("title", "content", attachment);
Gili
fuente
10
Eso es mucho copiar + pegar cuando solo uno o dos párrafos son relevantes.
Garret Wilson el
47
Lamentablemente, esta explicación no aborda la preocupación de cuándo la persona que llama, por ejemplo, analizar cierta información puede ser opcional. Con la sobrecarga del método (como se recomienda anteriormente), el código de llamada tiene que decir: "¿Está presente X? Si es así, llamaré al método sobrecargado A. ¿Está presente Y? Tendré que llamar al método B. están presentes, tendré que llamar al método sobrecargado C. " Y así. Puede haber una buena respuesta a esto, pero esta explicación de "por qué" no lo cubre.
Garret Wilson el
99
Además, cuando se trata de colecciones, existe una clara diferencia entre una colección vacía y ninguna colección. Por ejemplo, un caché. ¿Fue una señorita caché? vacío opcional / nulo. ¿Hubo un golpe de caché que resulta ser una colección vacía? Completo opcional / colección.
Ajax
1
@Ajax Creo que estás malinterpretando el artículo. Están citando un punto defendido por el libro Effective Java , que dice que cuando un tipo de retorno de método es una Colección (no un objeto arbitrario como devolvería un caché), debería favorecer la devolución de una colección vacía en lugar de nullo Optional.
Gili
44
Claro, debe favorecerlo , pero no siempre tiene control sobre algún código y, en un sentido muy real, es posible que desee diferenciar entre "hay un valor y es una colección vacía" versus "no hay valor definido (todavía) ". Dado que "magic null" también es una práctica desaconsejada, depende de usted, el desarrollador, elegir la opción menos mala. Prefiero vacío opcional para representar una falta de caché en lugar de una colección vacía, ya que el valor real en caché puede ser una colección vacía.
Ajax
86

Casi no hay buenas razones para no usar Optionalcomo parámetros. Los argumentos en contra de esto se basan en argumentos de la autoridad (ver Brian Goetz; su argumento es que no podemos aplicar opciones no nulas) o que los Optionalargumentos pueden ser nulos (esencialmente el mismo argumento). Por supuesto, cualquier referencia en Java puede ser nula, debemos alentar las reglas que impone el compilador, no la memoria de los programadores (lo cual es problemático y no se escala).

Los lenguajes de programación funcional fomentan los Optionalparámetros. Una de las mejores formas de usar esto es tener múltiples parámetros opcionales y liftM2usar una función asumiendo que los parámetros no están vacíos y devolviendo un opcional (ver http://www.functionaljava.org/javadoc/4.4/functionaljava/fj/ data / Option.html # liftM2-fj.F- ). Desafortunadamente, Java 8 ha implementado una biblioteca muy limitada que admite opcional.

Como programadores de Java, solo deberíamos usar null para interactuar con bibliotecas heredadas.

Mark Perry
fuente
3
¿Qué tal usar @Nonnully @Nullabledesde javax.annotation en su lugar? Los uso ampliamente en una biblioteca que desarrollo, y el soporte proporcionado por el IDE (IntelliJ) es muy bueno.
Rogério
1
Eso está bien, pero debe usar esta anotación en todas partes y necesita una biblioteca para admitir métodos como map, flatMap / bind, liftM2, secuencia, etc.
Mark Perry
14
Los lenguajes de programación funcional fomentan los parámetros opcionales. Cita necesaria. La mayoría de las funciones no deberían tomar una opción; en cambio, la responsabilidad de tratar (usando funciones apropiadas de orden superior) con la presencia o ausencia de un valor depende de quien llama la función en cuestión.
jub0bs
55
Esta. De hecho, ninguna de las respuestas es lo suficientemente convincente, y ninguna de ellas responde a esta pregunta específica "¿por qué usar opcionales como parámetros de método se considera una mala práctica, mientras que anotar parámetros de método @NonNulles totalmente correcto si tienen el mismo propósito de diferentes maneras? Para mí, solo hay un argumento que tiene al menos algo de sentido: "Opcional debería usarse para proporcionar mejores API que tengan un tipo de retorno claro. Sin embargo, para argumentos de método, pueden usarse funciones sobrecargadas". - Aún así, no creo que este sea un argumento lo suficientemente fuerte.
Utku Özdemir el
1
Por supuesto, preferible a nulo, pero lo que es aún más preferible es no necesitar muchos valores opcionales en primer lugar porque un buen diseño: D
yeoman
12

Este consejo es una variante de la regla general "sea lo más inespecífico posible con respecto a las entradas y lo más específico posible con respecto a las salidas".

Por lo general, si tiene un método que toma un valor simple no nulo, puede asignarlo sobre Optional, por lo que la versión simple es estrictamente más inespecífica con respecto a las entradas. Sin embargo, hay un montón de posibles razones por las cuales querrías requerir una Optionaldiscusión:

  • desea que su función se use junto con otra API que devuelve un Optional
  • Su función debe devolver algo diferente a un vacío Optionalsi el valor dado está vacío
  • Piensas que Optionales tan asombroso que cualquiera que use tu API debería estar obligado a aprender sobre él;
llogiq
fuente
10

El patrón con Optionales para evitar volver null . Todavía es perfectamente posible pasar nulla un método.

Si bien estos aún no son realmente oficiales, puede usar anotaciones de estilo JSR-308 para indicar si acepta o no nullvalores en la función. Tenga en cuenta que tendría que tener las herramientas adecuadas para identificarlo realmente, y proporcionaría más de una comprobación estática que una política de tiempo de ejecución exigible, pero ayudaría.

public int calculateSomething(@NotNull final String p1, @NotNull final String p2) {}
Makoto
fuente
El problema aquí es más bien que @NotNull no es el caso predeterminado y debe ser anotado explícitamente, por lo tanto, repetitivo y cosas que la gente simplemente no hará debido a la pereza.
dwegener
1
@dwegener Sí, pero Optionaltampoco soluciona el problema, de ahí mi sugerencia para las anotaciones.
Makoto
2
Es mucho más difícil ignorar Opcional que ignorar una anotación que solo notará si lee los documentos / fuente o si sus herramientas pueden atraparlo (el análisis estático no siempre puede determinar la nulabilidad correctamente).
Ajax
Tenga en cuenta que @Nullable puede no significar que "acepta" nulo como un valor válido, es decir, que no arroje ninguna excepción. Puede significar que se protege contra este caso, pero aún arrojará una excepción (esta es la semántica de Findbugs). Entonces puede introducir ambigüedad con tales anotaciones en lugar de claridad.
tkruse
No estoy seguro de qué ambigüedad hay @ user2986984. "No manejar nulo" solo podría significar de manera realista que se lanza una excepción.
Makoto
7

Esto me parece un poco tonto, pero la única razón por la que puedo pensar es que los argumentos de objeto en los parámetros del método ya son opcionales de alguna manera, pueden ser nulos. Por lo tanto, obligar a alguien a tomar un objeto existente y envolverlo en una opción no tiene sentido.

Dicho esto, encadenar métodos que toman / devuelven opciones es algo razonable, por ejemplo, tal vez mónada.

Steve B.
fuente
77
¿No pueden devolverse valores y campos también nulos? Entonces, ¿no Optionaltiene sentido por completo?
Samuel Edwin Ward
6

Echa un vistazo a JavaDoc en JDK10, https://docs.oracle.com/javase/10/docs/api/java/util/Optional.html , se agrega una nota de API:

Nota de API: Opcional está destinado principalmente para su uso como un tipo de retorno de método donde existe una clara necesidad de representar "sin resultado", y donde el uso de nulo puede causar errores.

Xiaolong
fuente
4

Mi opinión es que Opcional debería ser una Mónada y estos no son concebibles en Java.

En la programación funcional, se trata de funciones puras y de orden superior que toman y componen sus argumentos únicamente en función de su "tipo de dominio comercial". La composición de funciones que se alimentan, o cuyo cálculo debe informarse, al mundo real (los llamados efectos secundarios) requiere la aplicación de funciones que se encarguen de desempaquetar automáticamente los valores de las mónadas que representan el mundo exterior (Estado, Configuración, Futuros, Quizás, Cualquiera, Escritor, etc ...); Esto se llama levantar. Puedes pensarlo como una especie de separación de preocupaciones.

Mezclar estos dos niveles de abstracción no facilita la legibilidad, por lo que es mejor evitarlo.

Remolino
fuente
3

Otra razón para tener cuidado al pasar un Optionalparámetro as es que un método debe hacer una cosa ... Si pasa un Optionalparámetro, podría favorecer hacer más de una cosa, podría ser similar a pasar un parámetro booleano.

public void method(Optional<MyClass> param) {
     if(param.isPresent()) {
         //do something
     } else {
         //do some other
     }
 }
Pau
fuente
Creo que esa no es una buena razón. Se podría aplicar la misma lógica para verificar si param es nulo cuando no se usa opcional. En realidad, este if(param.isPresent())no es el mejor enfoque para usar Opcional, en su lugar puede usar:param.forEach(() -> {...})
hdkrus
Tampoco me gusta la idea de pasar parámetros anulables. De todos modos, dije que podrías favorecer, por supuesto, hay excepciones, puedes usarlo, depende de ti, solo úsalo con cuidado, eso es todo. No hay ninguna regla que se aplique a todos los escenarios.
Pau
2

Aceptar Opcional como parámetros provoca un ajuste innecesario a nivel de la persona que llama.

Por ejemplo en el caso de:

public int calculateSomething(Optional<String> p1, Optional<BigDecimal> p2 {}

Suponga que tiene dos cadenas no nulas (es decir, devueltas por algún otro método):

String p1 = "p1"; 
String p2 = "p2";

Estás obligado a envolverlos en Opcional incluso si sabes que no están vacíos.

Esto empeora aún más cuando tienes que componer con otras estructuras "asignables", es decir. Eithers :

Either<Error, String> value = compute().right().map((s) -> calculateSomething(
< here you have to wrap the parameter in a Optional even if you know it's a 
  string >));

árbitro:

los métodos no deberían esperar la Opción como parámetros, esto casi siempre es un olor a código que indica una fuga de flujo de control de la persona que llama a la persona que llama, debe ser responsabilidad de la persona que llama verificar el contenido de una Opción

árbitro. https://github.com/teamdigitale/digital-citizenship-functions/pull/148#discussion_r170862749

gpilotino
fuente
1

Creo que es porque usualmente escribes tus funciones para manipular datos, y luego las levantas para Optionalusar mapfunciones similares. Esto le agrega el Optionalcomportamiento predeterminado . Por supuesto, puede haber casos en los que sea necesario escribir su propia función auxiliar que funcione Optional.

Danil Gaponov
fuente
1

Creo que la resonancia del ser es que primero debe verificar si Opcional es nulo en sí mismo y luego tratar de evaluar el valor que envuelve. Demasiadas validaciones innecesarias.

Macchiatow
fuente
2
Pasar una referencia opcional nula puede considerarse un error de programación (porque Opcional proporciona una forma explícita de pasar un valor "vacío"), por lo que no vale la pena verificarlo, a menos que desee evitar lanzar excepciones en todos los casos.
pvgoran
1

Los opcionales no están diseñados para este propósito, como lo explicó Brian Goetz .

Siempre puede usar @Nullable para denotar que un argumento de método puede ser nulo. El uso de un opcional no le permite realmente escribir la lógica de su método de manera más clara.

Kieran
fuente
55
Lo siento, pero no puedo estar de acuerdo con el argumento "no fue diseñado" o "alguien recomienda no hacerlo". Un ingeniero deberíamos ser específicos. Usar @Nullable es mucho peor que usar Opcional, porque las Opcionales son mucho más detalladas desde el punto de vista de la API. No veo ninguna buena razón contra el uso de los opcionales como argumentos (siempre que no desee utilizar la sobrecarga de métodos)
Kacper86
0

Un enfoque más, lo que puedes hacer es

// get your optionals first
Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();

// bind values to a function
Supplier<Integer> calculatedValueSupplier = () -> { // your logic here using both optional as state}

Una vez que haya creado una función (proveedor en este caso) podrá pasarla como cualquier otra variable y podrá llamarla utilizando

calculatedValueSupplier.apply();

La idea aquí es si tiene un valor opcional o no será un detalle interno de su función y no estará en el parámetro. Pensar funciones cuando se piensa en opcional como parámetro es en realidad una técnica muy útil que he encontrado.

En cuanto a su pregunta si realmente debería hacerlo o no, se basa en su preferencia, pero como otros dijeron, hace que su API sea fea, por decir lo menos.

Swaraj Yadav
fuente
0

Al principio, también preferí pasar los Opcionales como parámetro, pero si cambia de una perspectiva de Diseñador de API a una perspectiva de Usuario de API, verá las desventajas.

Para su ejemplo, donde cada parámetro es opcional, sugeriría cambiar el método de cálculo en una clase propia como la siguiente:

Optional<String> p1 = otherObject.getP1();
Optional<BigInteger> p2 = otherObject.getP2();

MyCalculator mc = new MyCalculator();
p1.map(mc::setP1);
p2.map(mc::setP2);
int result = mc.calculate();
Torsten
fuente
0

Sé que esta pregunta se trata más de opiniones que de hechos concretos. Pero recientemente pasé de ser un desarrollador de .net a uno de Java, por lo que solo me uní recientemente a la fiesta Opcional. Además, preferiría decir esto como un comentario, pero dado que mi nivel de puntos no me permite comentar, me veo obligado a poner esto como una respuesta.

Lo que he estado haciendo, que me ha servido bien como regla general. Es usar los opcionales para los tipos de retorno, y solo usar los opcionales como parámetros, si requiero tanto el valor de Opcional como el clima o no, el Opcional tenía un valor dentro del método.

Si solo me importa el valor, verifico isPresent antes de llamar al método, si tengo algún tipo de registro o lógica diferente dentro del método que depende de si el valor existe, entonces felizmente pasaré el Opcional.

Blair
fuente
0

Esto se debe a que tenemos requisitos diferentes para un usuario de API y un desarrollador de API.

Un desarrollador es responsable de proporcionar una especificación precisa y una implementación correcta. Por lo tanto, si el desarrollador ya sabe que un argumento es opcional, la implementación debe tratarlo correctamente, ya sea un valor nulo u opcional. La API debe ser lo más simple posible para el usuario, y nulo es lo más simple.

Por otro lado, el resultado se pasa del desarrollador de API al usuario. Sin embargo, la especificación es completa y detallada, aún existe la posibilidad de que el usuario no lo sepa o simplemente sea flojo para tratarla. En este caso, el resultado Opcional obliga al usuario a escribir un código adicional para lidiar con un posible resultado vacío.

speedogoo
fuente
0

En primer lugar, si está utilizando el método 3, puede reemplazar esas últimas 14 líneas de código con esto:

int result = myObject.calculateSomething(p1.orElse(null), p2.orElse(null));

Las cuatro variaciones que escribió son métodos convenientes . Solo debes usarlos cuando sean más convenientes. Ese es también el mejor enfoque. De esa manera, la API tiene muy claro qué miembros son necesarios y cuáles no. Si no desea escribir cuatro métodos, puede aclarar las cosas por cómo nombra sus parámetros:

public int calculateSomething(String p1OrNull, BigDecimal p2OrNull)

De esta manera, está claro que se permiten valores nulos.

Su uso de p1.orElse(null)ilustra cuán detallado es nuestro código cuando se usa Opcional, lo cual es parte de por qué lo evito. Opcional fue escrito para la programación funcional. Las corrientes lo necesitan. Sus métodos probablemente nunca deberían devolver Opcional a menos que sea necesario usarlos en la programación funcional. Hay métodos, como Optional.flatMap()método, que requieren una referencia a una función que devuelve Opcional. Aquí está su firma:

public <U> Optional<U> flatMap(Function<? super T, ? extends Optional<? extends U>> mapper)

Por lo general, esa es la única buena razón para escribir un método que devuelve Opcional. Pero incluso allí, se puede evitar. Puede pasar un captador que no devuelve Opcional a un método como flatMap (), envolviéndolo en otro método que convierta la función al tipo correcto. El método de envoltura se ve así:

public static <T, U> Function<? super T, Optional<U>> optFun(Function<T, U> function) {
    return t -> Optional.ofNullable(function.apply(t));
}

Supongamos que tienes un captador como este: String getName()

No puede pasarlo a flatMap así:

opt.flatMap(Widget::getName) // Won't work!

Pero puedes pasarlo así:

opt.flatMap(optFun(Widget::getName)) // Works great!

Fuera de la programación funcional, se deben evitar los opcionales.

Brian Goetz lo dijo mejor cuando dijo esto:

La razón por la que se agregó Opcional a Java es porque esto:

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 limpio 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;
Miguel Muñoz
fuente
1
Bueno, esa es UNA de las razones por las que se agregó a Java. Hay muchos otros más. Reemplazar cadenas largas de declaraciones 'if' anidadas que atraviesan una estructura de datos con una sola secuencia de llamadas encadenadas a Opcional.map es mi favorito personal. El mundo de programación de Functional Languages ​​tiene muchos usos interesantes para Opcional además de simplemente reemplazar cheques nulos como este.
Algún tipo