java optional

Java Opcional y orElse



optional (7)

El problema está en orden de ejecución. Está tratando de calcular el valor para .orElse (...) y lanza MyException en .orElseThrow.

En otras palabras, si t no es nulo, el siguiente flujo de ejecución es el siguiente:

1) calcular el valor de

Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException"))

2) use el valor de (1) en

Optional.ofNullable("notnull").orElse(...)

Soy nuevo en las opciones Java pero veo este código escrito por otro desarrollador y no lo entiendo:

String t = null; Optional.ofNullable("notnull") .orElse( Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException")) );

¿Por qué este código arroja la excepción? ¿Por qué incluso va a la rama "o Else"?

¿Esto se debe a una orden de ejecución extraña? Entonces, ¿el valor del primer opcional no se establece antes de evaluar la rama orElse?


El resultado se espera porque en Java antes de invocar un método que toma un parámetro, lo que hace la JVM antes es evaluar el valor del parámetro.
Y ese es el valor del parámetro de la invocación .orElse() :

Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException"))

Como t refiere a null , se espera el lanzamiento de excepción.


Eso es porque el código dentro de orElse() siempre será evaluado. En otras palabras, se ejecutará incluso si especifica un Optional no vacío, por eso se lanzará la Exception .

Si orElse() sección orElse() artículo Java Opcional - orElse () vs orElseGet () , puede ver eso en su ejemplo, donde dice:

Podemos inferir fácilmente que el parámetro de orElse () se evalúa incluso cuando se tiene un Opcional no vacío.


Hay algunas cosas que debe tener en cuenta sobre Optional :

  1. Si se sabe que el valor que se está ajustando es nulo o no, use Optional.of() u Optional.empty() . Si no está seguro, (por ejemplo, el valor es una variable que obtuvo de otro lugar) use Optional.ofNullable()

  2. Hay una diferencia importante entre orElse() y Optional.orElseGet() .

    1. orElse toma un valor ya calculado, si se proporciona una expresión, se ejecuta y evalúa en ese mismo momento. Esto está sucediendo en el código en cuestión . Por lo tanto, esta otra variante debe usarse para valores o primitivas ya disponibles.

    2. orElseGet toma una función de proveedor que solo se ejecuta cuando se evalúa la cadena opcional y se solicita un valor alternativo. Esto debería usarse donde el valor alternativo es costoso de producir o calcular.

    // Fine Optional<String> name = Optional.of(someValue).orElse("defaultName"); // But this: Optional<String> name = Optional.of(someValue).orElse(db.queryName()); // Is better written as following, as it saves you from an expensive operation Optional<String> name = Optional.of(someValue).orElseGet(() -> db.queryName());


La secuencia orElse nunca se invoca, pero el método en sí se ejecuta. Esto significa que también se le pasa el parámetro del método. Por lo tanto, se Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException")) la parte Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException")) independientemente del valor pasado a la primera llamada Optional.ofNullable .

Si no desea que esto suceda, deberá pasar un Supplier como este:

String t = null; Optional.ofNullable("notnull") .orElseGet( () -> Optional.ofNullable(t).orElseThrow(() -> new RuntimeException("MyException")) );

El proveedor solo se invoca cuando se invoca la secuencia orElseGet . Tenga en cuenta que necesitará una RuntimeException lugar de una excepción marcada para poder separarse del proveedor.


Lo que escribiste es igual a esto:

String t = null; String myException = Optional.ofNullable(t).orElseThrow(() -> new Exception("MyException")); Optional.ofNullable("notnull").orElse(myException);

Parte o orElse de Optional se evalúa antes de saber si su valor es nulo o no. Si desea una evaluación "Lazy" , considere el método orElseGet .


Realmente me pregunto por qué este código se ha escrito de esta manera. Parece que necesitaba desencadenar una excepción con un valor NULL explícito agregado al opcional.

Como ya se dijo al usar orElse() lugar de orElseGet() el método se evalúa sin importar el valor de T (por ejemplo, Optional<T> ).

Lo usaría para una mejor moda y comprensión:

String value = "notnull"; // could be null Optional.ofNullable(value) .orElseThrow(MyException::new);

En caso de que el valor sea NULL, se activa la excepción.

Tenga en cuenta que puede usar referencias de métodos para invocar excepciones