Sé cómo crear una referencia a un método que tiene un String
parámetro y devuelve un int
, es:
Function<String, Integer>
Sin embargo, esto no funciona si la función arroja una excepción, digamos que se define como:
Integer myMethod(String s) throws IOException
¿Cómo definiría esta referencia?
Respuestas:
Tendrá que hacer uno de los siguientes.
Si es su código, defina su propia interfaz funcional que declare la excepción marcada:
y úsalo:
De lo contrario, envuelva
Integer myMethod(String s)
un método que no declare una excepción marcada:y entonces:
o:
fuente
Consumer
oFunction
si usa métodos predeterminados, consulte mi respuesta a continuación.(String t) -> myWrappedMethod(t)
, la referencia del métodothis::myWrappedMethod
también se puede utilizar.En realidad, puede ampliar
Consumer
(yFunction
etc.) con una nueva interfaz que maneja excepciones, ¡utilizando los métodos predeterminados de Java 8 !Considere esta interfaz (se extiende
Consumer
):Entonces, por ejemplo, si tiene una lista:
Si desea consumirlo (por ejemplo, con
forEach
) con algún código que arroje excepciones, tradicionalmente habría configurado un bloque try / catch:Pero con esta nueva interfaz, puede crear una instancia con una expresión lambda y el compilador no se quejará:
¡O incluso solo para que sea más sucinto !:
Actualización : Parece que hay una muy buena parte de la biblioteca de servicios de Durian llamada Errores que se puede usar para resolver este problema con mucha más flexibilidad. Por ejemplo, en mi implementación anterior, he definido explícitamente la política de manejo de errores (
System.out...
othrow RuntimeException
), mientras que los Errores de Durian le permiten aplicar una política sobre la marcha a través de un amplio conjunto de métodos de utilidad. Gracias por compartirlo , @NedTwigg !.Uso de la muestra:
fuente
Creo que la
Errors
clase de Durian combina muchas de las ventajas de las diversas sugerencias anteriores.Para incluir a Durian en su proyecto, puede:
com.diffplug.durian:durian:3.3.0
Throwing.java
yErrors.java
fuente
Esto no es específico de Java 8. Está intentando compilar algo equivalente a:
fuente
Descargo de responsabilidad: todavía no he usado Java 8, solo he leído sobre él.
Function<String, Integer>
no arrojaIOException
, así que no puedes poner ningún código en esothrows IOException
. Si está llamando a un método que espera unFunction<String, Integer>
, entonces la lambda que pasa a ese método no puede arrojarIOException
, punto. Puede escribir una lambda como esta (creo que esta es la sintaxis lambda, no estoy seguro):O, si el método al que le está pasando el lambda es uno que usted mismo escribió, puede definir una nueva interfaz funcional y usarla como tipo de parámetro en lugar de
Function<String, Integer>
:fuente
@FunctionalInterface
anotación no es necesaria para que sea utilizable para lambdas. Sin embargo, se recomienda para el control de la cordura.Si no le importa usar una lib de terceros ( Vavr ), puede escribir
También tiene el llamado Try mónada que maneja los errores:
Por favor lea más aquí .
Descargo de responsabilidad: soy el creador de Vavr.
fuente
Puedes usar unthrow wrapper
o
fuente
Sin embargo, puede crear su propia FunctionalInterface que se muestra a continuación.
luego impleméntelo usando Lambdas o referencias como se muestra a continuación.
fuente
Usted puede.
Extendiendo @marcg 's
UtilException
y agregando genéricos<E extends Exception>
cuando sea necesario: de esta manera, el compilador lo obligará nuevamente a agregar cláusulas de lanzamiento y todo es como si pudiera lanzar excepciones comprobadas de forma nativa en las transmisiones de java 8.fuente
Tuve este problema con Class.forName y Class.newInstance dentro de una lambda, así que simplemente hice:
Dentro de la lambda, en lugar de llamar a Class.forName ("myClass"). NewInstance () acabo de llamar a uncheckedNewInstanceForName ("myClass")
fuente
Otra solución usando un contenedor de funciones sería devolver una instancia de un contenedor de su resultado, digamos Éxito, si todo salió bien, ya sea una instancia de, digamos Fallo.
Algunos códigos para aclarar cosas:
Un caso de uso simple:
fuente
Este problema también me ha estado molestando; Por eso he creado este proyecto .
Con ella puedes hacer:
Hay un total de 39 interfaces definidas por el JDK que tienen dicho
Throwing
equivalente; esos son todos@FunctionalInterface
s usados en streams (la baseStream
pero tambiénIntStream
,LongStream
yDoubleStream
).Y a medida que cada uno de ellos extiende su contraparte que no arroja, también puedes usarlos directamente en lambdas:
El comportamiento predeterminado es que cuando su lambda de lanzamiento arroja una excepción marcada, se
ThrownByLambdaException
produce a con la excepción marcada como la causa. Por lo tanto, puede capturar eso y obtener la causa.Otras características están disponibles también.
fuente
@FunctionalInterface public interface SupplierWithCE<T, X extends Exception> { T get() throws X; }
- de esta manera, el usuario no necesita atraparThrowable
, sino la excepción marcada específica.ThrownByLambdaException
, tendrá la excepción original como causa (o puede usarrethrow(...).as(MyRuntimeException.class)
)Throwing.runnable()
y otros, siempre con capacidades de encadenamientoYa hay muchas respuestas excelentes publicadas aquí. Solo intento resolver el problema con una perspectiva diferente. Son solo mis 2 centavos, corrígeme si me equivoco en alguna parte.
La cláusula Throws en FunctionalInterface no es una buena idea
Creo que esto probablemente no sea una buena idea para forzar lanzamientos IOException debido a las siguientes razones
Esto me parece un antipatrón para Stream / Lambda. La idea es que la persona que llama decidirá qué código proporcionar y cómo manejar la excepción. En muchos escenarios, la IOException podría no ser aplicable para el cliente. Por ejemplo, si el cliente obtiene valor de la memoria caché / memoria en lugar de realizar E / S real.
Además, el manejo de excepciones en las transmisiones se vuelve realmente horrible. Por ejemplo, aquí se verá mi código si uso su API
¿No es feo? Además, como mencioné en mi primer punto, que el método doSomeOperation puede o no lanzar IOException (dependiendo de la implementación del cliente / llamante), pero debido a la cláusula throws en su método FunctionalInterface, siempre tengo que escribir el trata de atraparlo.
¿Qué hago si realmente sé que esta API arroja IOException
Entonces, probablemente estamos confundiendo la interfaz funcional con las interfaces típicas. Si sabe que esta API arrojará IOException, entonces probablemente también conozca algunos comportamientos predeterminados / abstractos. Creo que debería definir una interfaz e implementar su biblioteca (con implementación predeterminada / abstracta) de la siguiente manera
Pero, el problema try-catch todavía existe para el cliente. Si uso su API en la transmisión, todavía necesito manejar IOException en el horrible bloque try-catch.
Proporcione una API amigable de transmisión predeterminada de la siguiente manera
El método predeterminado toma el objeto del consumidor como argumento, que será responsable de manejar la excepción. Ahora, desde el punto de vista del cliente, el código se verá así
Bien verdad? Por supuesto, se podría usar logger u otra lógica de manejo en lugar de Exception :: printStackTrace.
También puede exponer un método similar a https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#exceptionally-java.util.function.Function- . Lo que significa que puede exponer otro método, que contendrá la excepción de la llamada al método anterior. La desventaja es que ahora está haciendo que sus API tengan estado, lo que significa que necesita manejar la seguridad de subprocesos y que eventualmente se convertirá en un éxito en el rendimiento. Sin embargo, es solo una opción a considerar.
fuente
Stream
Excepción planteada. Por lo tanto, me gusta la idea de tener un controlador de excepciones y filtrar los resultados que no son válidos. Tenga en cuenta que su MyAmazingAPI es efectivamente unaFunctionalInterface
(por lo tanto, puede agregar la anotación @FunctionalInterface). También podría tener un valor predeterminado en lugar de usarOptional.empty()
.El lenguaje furtivo disimulado permite evitar la
CheckedException
expresión de Lambda. Ajustar aCheckedException
en aRuntimeException
no es bueno para el manejo estricto de errores.Se puede utilizar como una
Consumer
función utilizada en una colección Java.Aquí hay una versión simple y mejorada de la respuesta de jib .
Esto simplemente envuelve la lambda en un nuevo lanzamiento . Hace
CheckedException
volver aException
tirar cualquiera que haya sido arrojado en tu lambda.Encuentre un código completo y pruebas unitarias aquí .
fuente
Puedes usar ET para esto. ET es una pequeña biblioteca Java 8 para conversión / traducción de excepciones.
Con ET se ve así:
ExceptionTranslator
las instancias son seguras para subprocesos y pueden ser compartidas por múltiples componentes. Puede configurar reglas de conversión de excepciones más específicas (por ejemploFooCheckedException -> BarRuntimeException
) si lo desea. Si no hay otras reglas disponibles, las excepciones marcadas se convierten automáticamente aRuntimeException
.(Descargo de responsabilidad: soy el autor de ET)
fuente
Lo que estoy haciendo es permitir que el usuario dé el valor que realmente desea en caso de excepción. Así que tengo algo parecido a esto
Y esto se puede llamar así:
fuente
Si no le importa usar una biblioteca de terceros, con cyclops-react , una biblioteca a la que contribuyo, puede usar la API FluentFunctions para escribir
ofChecked toma una función comprobada jOOλ y devuelve la referencia suavizada a un JDK estándar (sin marcar) java.util.function.Function.
Alternativamente, puede seguir trabajando con la función capturada a través de la API de FluentFunctions.
Por ejemplo, para ejecutar su método, reintentándolo hasta 5 veces y registrando su estado, puede escribir
fuente
De manera predeterminada, la función Java 8 no permite generar excepciones y, como se sugiere en varias respuestas, hay muchas maneras de lograrlo, una de ellas es:
Definir como:
Y agregue
throws
otry/catch
la misma excepción en el método de llamada.fuente
Cree un tipo de devolución personalizado que propague la excepción marcada. Esta es una alternativa a la creación de una nueva interfaz que refleja la interfaz funcional existente con la ligera modificación de una "excepción de lanzamiento" en el método de la interfaz funcional.
Definición
CheckedValueSupplier
CheckedValue
Uso
¿Que esta pasando?
Se crea una única interfaz funcional que arroja una excepción marcada (
CheckedValueSupplier
). Esta será la única interfaz funcional que permite excepciones marcadas. Todas las demás interfaces funcionales aprovecharánCheckedValueSupplier
para envolver cualquier código que arroje una excepción marcada.La
CheckedValue
clase mantendrá el resultado de ejecutar cualquier lógica que arroje una excepción marcada. Esto evita la propagación de una excepción marcada hasta el punto en que el código intenta acceder al valor queCheckedValue
contiene una instancia .Los problemas con este enfoque.
CheckedValue#get()
se llama.Consumer et al.
Algunas interfaces funcionales (
Consumer
por ejemplo) deben manejarse de manera diferente ya que no proporcionan un valor de retorno.Función en lugar del consumidor
Un enfoque es usar una función en lugar de un consumidor, que se aplica cuando se manejan flujos.
Escalar
Alternativamente, siempre puede escalar a a
RuntimeException
. Hay otras respuestas que cubren la escalada de una excepción marcada desde dentro de aConsumer
.No consumir
Simplemente evite las interfaces funcionales y use un bucle for bien diseñado.
fuente
Utilizo una función de utilidad sobrecargada llamada
unchecked()
que maneja múltiples casos de uso.ALGUNOS USOS DE EJEMPLO
UTILIDADES DE APOYO
fuente
Varias de las soluciones ofrecidas utilizan un argumento genérico de E para pasar el tipo de excepción que se produce.
Vaya un paso más allá y, en lugar de pasar el tipo de excepción, pase un Consumidor del tipo de excepción, como en ...
Puede crear varias variaciones reutilizables
Consumer<Exception>
que cubrirían las necesidades comunes de manejo de excepciones de su aplicación.fuente
Haré algo genérico:
uso:
fuente
Usar
Jool Library
o decirjOOλ library
deJOOQ
. No solo proporciona interfaces manejadas de excepciones no verificadas, sino que también proporciona a la clase Seq muchos métodos útiles.Además, contiene interfaces funcionales con hasta 16 parámetros. Además, proporciona la clase Tuple que se usa en diferentes escenarios.
Jool Git Link
Específicamente en la búsqueda de la biblioteca para el
org.jooq.lambda.fi.util.function
paquete. Contiene todas las interfaces de Java-8 con Checked antepuesto. Consulte a continuación para referencia: -fuente
Soy el autor de una pequeña lib con algo de magia genérica para lanzar cualquier Excepción de Java a cualquier lugar sin la necesidad de atraparlas o envolverlas
RuntimeException
.Uso:
unchecked(() -> methodThrowingCheckedException())
fuente: https://github.com/qoomon/unchecked-exceptions-java
fuente
fuente
<code>/<code>