Manejo de excepciones en java 8 lambda expresión


Manejo de excepciones en java 8 lambda expresión

Introduccion

Las expresiones Lambda se introdujeron en Java 8. Las expresiones Lambda pueden hacer que nuestro código sea más breve y la lógica empresarial más clara, pero la interfaz funcional utilizada en las expresiones lambda no maneja muy bien las excepciones, porque estas interfaces funcionales proporcionadas por JDK Por lo general, no se produce ninguna excepción, lo que significa que debemos manejar manualmente la excepción nosotros mismos.

Debido a que las excepciones se dividen en Excepción no marcada y Excepción marcada, las discutimos por separado.

Manejar excepción no verificada

La excepción no verificada también se llama RuntimeException, que generalmente ocurre debido a un problema en nuestro código. RuntimeException no necesita ser capturado. En otras palabras, si hay una RuntimeException, se puede compilar sin atraparla.

Veamos un ejemplo:

List<Integer> integers = Arrays.asList(1,2,3,4,5);
        integers.forEach(i -> System.out.println(1 / i));

Este ejemplo se puede compilar con éxito, pero hay un problema anterior, si hay un 0 en la lista, se generará una ArithmeticException.

Aunque esta es una excepción no verificada, aún queremos tratar con ella:

        integers.forEach(i -> {
            try {
                System.out.println(1 / i);
            } catch (ArithmeticException e) {
                System.err.println(
                        "Arithmetic Exception occured : " + e.getMessage());
            }
        });

En el ejemplo anterior, usamos try and catch para manejar la excepción, que es simple pero destruye la mejor práctica de la expresión lambda. El código se hincha.

Movemos el try y catch a un 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());
            }
        };
    }

Entonces la llamada original se convierte así:

integers.forEach(lambdaWrapper(i -> System.out.println(1 / i)));

Pero el contenedor sobre la captura ArithmeticException fija, lo adaptaremos a una clase más general:

    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;
                }
            }
        };
    }

La clase anterior pasa a una clase y la convierte en una excepción. Si se puede emitir, se procesa, de lo contrario se genera una excepción.

Después de este procesamiento, llamamos así:

integers.forEach(
                consumerWrapperWithExceptionClass(
                        i -> System.out.println(1 / i),
                        ArithmeticException.class));

Manejar la excepción marcada

La excepción marcada es una excepción que debe manejarse, veamos un ejemplo:

    static void throwIOException(Integer integer) throws IOException {
    }
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
        integers.forEach(i -> throwIOException(i));

Anteriormente definimos un método que arroja una IOException, que es una Excepción marcada y necesita ser manejada, por lo que en lo siguiente para Cada, el programa no se compilará porque la excepción correspondiente no se maneja.

La forma más fácil es intentar atrapar, como se muestra a continuación:

        integers.forEach(i -> {
            try {
                throwIOException(i);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });

Por supuesto, las desventajas de este enfoque ya se han mencionado anteriormente. De manera similar, podemos definir un nuevo método de envoltura:

    static <T> Consumer<T> consumerWrapper(
            ThrowingConsumer<T, Exception> throwingConsumer) {

        return i -> {
            try {
                throwingConsumer.accept(i);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        };
    }

Llamamos así:

integers.forEach(consumerWrapper(i -> throwIOException(i)));

También podemos encapsular la excepción:

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);
                }
            }
        };
    }

Entonces llámalo así:

integers.forEach(consumerWrapperWithExceptionClass(
                i -> throwIOException(i), IOException.class));

Resumen

Este artículo describe cómo manejar las excepciones marcadas y no marcadas en las expresiones lambda, espero brindarle ayuda.

Ejemplo de este artículo https://github.com/ddean2009/learn-java-streams/tree/master/lambda-exception

Bienvenido a prestar atención a mi número público: esas cosas del programa, ¡más emocionante esperando por ti!
Para obtener más información, visite www.flydean.com.

172 artículos originales publicados · ganó 241 · vistas 480,000+

Supongo que te gusta

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