Diretório do artigo
Manipulação de exceção na expressão java 8 lambda
1. Introdução
As expressões lambda foram introduzidas no Java 8. As expressões lambda podem tornar nosso código mais breve e a lógica de negócios mais clara, mas a Interface Funcional usada nas expressões lambda não trata muito bem as exceções, porque essas interfaces funcionais fornecidas pelo JDK Normalmente, nenhuma exceção é lançada, o que significa que precisamos lidar manualmente com a exceção.
Como as exceções são divididas em Exceção não verificada e Exceção verificada, as discutimos separadamente.
Lidar com exceção não verificada
A exceção não verificada também é chamada de RuntimeException, que geralmente ocorre devido a um problema no nosso código. RuntimeException não precisa ser capturado. Em outras palavras, se houver uma RuntimeException, ela poderá ser compilada sem capturá-la.
Vejamos um exemplo:
List<Integer> integers = Arrays.asList(1,2,3,4,5);
integers.forEach(i -> System.out.println(1 / i));
Este exemplo pode ser compilado com êxito, mas há um problema acima; se houver um 0 na lista, uma ArithmeticException será lançada.
Embora essa seja uma exceção não verificada, ainda queremos lidar com ela:
integers.forEach(i -> {
try {
System.out.println(1 / i);
} catch (ArithmeticException e) {
System.err.println(
"Arithmetic Exception occured : " + e.getMessage());
}
});
No exemplo acima, usamos try e catch para manipular a exceção, que é simples, mas destrói a melhor prática da expressão lambda. O código fica inchado.
Movemos a tentativa e captura para um método wrapper:
static Consumer<Integer> lambdaWrapper(Consumer<Integer> consumer) {
return i -> {
try {
consumer.accept(i);
} catch (ArithmeticException e) {
System.err.println(
"Arithmetic Exception occured : " + e.getMessage());
}
};
}
Em seguida, a chamada original fica assim:
integers.forEach(lambdaWrapper(i -> System.out.println(1 / i)));
Mas o wrapper acima da captura ArithmeticException fixa, vamos adaptá-lo a uma classe mais geral:
static <T, E extends Exception> Consumer<T>
consumerWrapperWithExceptionClass(Consumer<T> consumer, Class<E> clazz) {
return i -> {
try {
consumer.accept(i);
} catch (Exception ex) {
try {
E exCast = clazz.cast(ex);
System.err.println(
"Exception occured : " + exCast.getMessage());
} catch (ClassCastException ccEx) {
throw ex;
}
}
};
}
A classe acima passa em uma classe e a lança como uma exceção.Se pode ser convertida, é processada, caso contrário, uma exceção é lançada.
Após esse processamento, chamamos assim:
integers.forEach(
consumerWrapperWithExceptionClass(
i -> System.out.println(1 / i),
ArithmeticException.class));
Identificador verificado Exceção
Exceção marcada é uma exceção que deve ser tratada, vejamos um exemplo:
static void throwIOException(Integer integer) throws IOException {
}
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
integers.forEach(i -> throwIOException(i));
Acima, definimos um método que lança uma IOException, que é uma exceção verificada e precisa ser manipulada; portanto, no forEach a seguir, o programa falhará na compilação porque a exceção correspondente não é manipulada.
A maneira mais fácil é tentar capturar, como mostrado abaixo:
integers.forEach(i -> {
try {
throwIOException(i);
} catch (IOException e) {
throw new RuntimeException(e);
}
});
Obviamente, as desvantagens dessa abordagem já foram mencionadas acima. Da mesma forma, podemos definir um novo método de wrapper:
static <T> Consumer<T> consumerWrapper(
ThrowingConsumer<T, Exception> throwingConsumer) {
return i -> {
try {
throwingConsumer.accept(i);
} catch (Exception ex) {
throw new RuntimeException(ex);
}
};
}
Chamamos assim:
integers.forEach(consumerWrapper(i -> throwIOException(i)));
Também podemos encapsular a exceção:
static <T, E extends Exception> Consumer<T> consumerWrapperWithExceptionClass(
ThrowingConsumer<T, E> throwingConsumer, Class<E> exceptionClass) {
return i -> {
try {
throwingConsumer.accept(i);
} catch (Exception ex) {
try {
E exCast = exceptionClass.cast(ex);
System.err.println(
"Exception occured : " + exCast.getMessage());
} catch (ClassCastException ccEx) {
throw new RuntimeException(ex);
}
}
};
}
Então chame assim:
integers.forEach(consumerWrapperWithExceptionClass(
i -> throwIOException(i), IOException.class));
Sumário
Este artigo descreve como lidar com exceções verificadas e não verificadas nas expressões lambda. Espero ajudar.
Exemplo deste artigo https://github.com/ddean2009/learn-java-streams/tree/master/lambda-exception
Bem-vindo a prestar atenção ao meu número público: essas coisas do programa, mais emocionante esperando por você!
Para mais informações, visite www.flydean.com