catch - throw exception inside lambda java
¿Por qué no puedo lanzar una excepción en una expresión Java 8 lambda? (2)
Puedes lanzar excepciones en lambdas.
Una lambda puede arrojar las mismas excepciones que la interfaz funcional implementada por la lambda.
Si el método de la interfaz funcional no tiene una cláusula throws, la lambda no puede lanzar CheckedExceptions. (Todavía puedes lanzar RuntimeExceptions).
En su caso particular, Map.forEach
utiliza un BiConsumer
como parámetro, BiConsumer se define como:
public interface BiConsumer<T, U> {
void accept(T t, U u);
}
Una expresión lambda para esta interfaz funcional no puede lanzar CheckedExceptions.
Los métodos en las interfaces funcionales definidos en el paquete java.util.function
no arrojan excepciones, pero puede usar otras interfaces funcionales o crear las suyas propias para poder lanzar excepciones, es decir, dada esta interfaz:
public interface MyFunctionalInterface<T> {
void accept(T t) throws Exception;
}
El siguiente código sería legal:
MyFunctionalInterface<String> f = (s)->throw new Exception("Exception thrown in lambda");
Esta pregunta ya tiene una respuesta aquí:
- Referencia de método 8 Java excepción no controlada 3 respuestas
Actualicé a Java 8 e intenté reemplazar una iteración simple a través de un Mapa con una nueva expresión de lamdba. El ciclo busca valores nulos y arroja una excepción si se encuentra uno. El antiguo código de Java 7 se ve así:
for (Map.Entry<String, String> entry : myMap.entrySet()) {
if(entry.getValue() == null) {
throw new MyException("Key ''" + entry.getKey() + "'' not found!");
}
}
Y mi intento de convertir esto a Java 8 se ve así:
myMap.forEach((k,v) -> {
if(v == null) {
// OK
System.out.println("Key ''" + k+ "'' not found!");
// NOK! Unhandled exception type!
throw new MyException("Key ''" + k + "'' not found!");
}
});
¿Alguien puede explicar por qué la declaración throw
no está permitida aquí y cómo podría corregirse?
La sugerencia de solución rápida de Eclipse no me parece correcta ... simplemente rodea la instrucción throw
con un bloque try-catch
:
myMap.forEach((k,v) -> {
if(v == null) {
try {
throw new MyException("Key ''" + k + "'' not found!");
}
catch (Exception e) {
e.printStackTrace();
}
}
});
No está permitido lanzar excepciones marcadas porque el método de void accept(T t, U u)
en la BiConsumer<T, U>
no arroja ninguna excepción. Y, como sabes, forEach
toma ese tipo.
public void forEach(BiConsumer<? super K, ? super V> action) { ... }
|
V
@FunctionalInterface
public interface BiConsumer<T, U> {
void accept(T t, U u); // <-- does throw nothing
}
Eso es cierto cuando estamos hablando de excepciones marcadas. Pero puede lanzar una excepción no verificada, por ejemplo, una IllegalArgumentException
:
new HashMap<String, String>()
.forEach((a, b) -> { throw new IllegalArgumentException(); });