Manipulação de exceção na expressão java 8 lambda


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

Publicado 172 artigos originais · ganhou 241 · visualizações 480,000+

Acho que você gosta

Origin blog.csdn.net/superfjj/article/details/105698541
Recomendado
Clasificación