Обработка исключений в лямбда-выражении java 8

Java

Обработка исключений в лямбда-выражении java 8

Введение

лямбда-выражения были введены в java 8, лямбда-выражения могут сделать наш код более кратким, а бизнес-логику более понятной, но функциональный интерфейс, используемый в лямбда-выражениях, не очень хорошо обрабатывает исключения, потому что эти функциональные интерфейсы, предоставляемые JDK, обычно не выбрасываются исключения, что означает, что нам нужно обрабатывать исключение вручную.

Поскольку исключения делятся на непроверенное исключение и проверенное исключение, мы обсуждаем их отдельно.

Обработка непроверенных исключений

Непроверенное исключение также называется RuntimeException, а RuntimeException обычно возникает из-за проблемы с нашим кодом. RuntimeException не нужно перехватывать. То есть, если есть исключение RuntimeException, его можно скомпилировать, не перехватывая.

Давайте посмотрим на пример:

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

Этот пример может быть успешно скомпилирован, но есть проблема выше, если в списке есть 0, будет выброшено исключение ArithmeticException.

Хотя это непроверенное исключение, мы все равно хотим его обработать:

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

В приведенном выше примере мы использовали try и catch для обработки исключений, что просто, но нарушает передовую практику лямбда-выражений. Код становится раздутым.

Мы перемещаем try, catch в метод-оболочку:

    static Consumer<Integer> lambdaWrapper(Consumer<Integer> consumer) {
        return i -> {
            try {
                consumer.accept(i);
            } catch (ArithmeticException e) {
                System.err.println(
                        "Arithmetic Exception occured : " + e.getMessage());
            }
        };
    }

Первоначальный вызов становится таким:

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

Но обертка выше исправила отлов ArithmeticException, давайте адаптируем его к более общему классу:

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

Вышеупомянутый класс передает класс и приводит его к исключению, если он может быть приведен, обрабатывает его, в противном случае генерирует исключение.

После этого мы вызываем его так:

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

Обработка отмеченных исключений

Checked Exception — это исключение, которое необходимо обработать.Давайте рассмотрим пример:

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

Выше мы определили метод, который генерирует IOException, которое является проверенным исключением и требует обработки, поэтому в следующем forEach программа не скомпилируется, поскольку соответствующее исключение не обрабатывается.

Самый простой способ - попробовать и поймать, следующим образом:

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

Конечно, недостатки этого подхода были упомянуты выше, аналогично мы можем определить новый метод-оболочку:

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

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

Мы называем это так:

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

Мы также можем посмотреть на исключение пакета:

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

Затем вызовите так:

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

Суммировать

В этой статье рассказывается, как обрабатывать проверенные и непроверенные исключения в лямбда-выражениях, и я надеюсь, что она поможет вам.

Примеры этой статьиGitHub.com/Dadean2009/приходите…

Добро пожаловать, обратите внимание на мой публичный номер: вас ждут самые интересные вещи о программе! Для получения дополнительной информации, пожалуйста, посетитеwww.flydean.com