Я знаю, как создать ссылку на метод, который имеет String
параметр и возвращает int
, это:
Function<String, Integer>
Однако, это не работает, если функция выдает исключение, скажем, что оно определено как:
Integer myMethod(String s) throws IOException
Как бы я определил эту ссылку?
Ответы:
Вам нужно будет выполнить одно из следующих действий.
Если это ваш код, тогда определите свой собственный функциональный интерфейс, который объявляет проверенное исключение:
и использовать это:
В противном случае, включите
Integer myMethod(String s)
метод, который не объявляет проверенное исключение:а потом:
или:
источник
Consumer
илиFunction
использовать методы по умолчанию - см. Мой ответ ниже.(String t) -> myWrappedMethod(t)
ссылки на методthis::myWrappedMethod
также можно использовать.Вы можете расширить
Consumer
(иFunction
т. Д.) Новым интерфейсом, который обрабатывает исключения - используя стандартные методы Java 8 !Рассмотрим этот интерфейс (расширяет
Consumer
):Тогда, например, если у вас есть список:
Если вы хотите использовать его (например, с
forEach
) с некоторым кодом, который генерирует исключения, вы бы традиционно установили блок try / catch:Но с этим новым интерфейсом вы можете создать его с помощью лямбда-выражения, и компилятор не будет жаловаться:
Или даже просто брось, чтобы быть более лаконичным!
Обновление : Похоже, что есть очень хорошая часть библиотеки утилит Durian под названием Errors, которую можно использовать для решения этой проблемы с гораздо большей гибкостью. Например, в моей реализации выше я явно определил политику обработки ошибок (
System.out...
илиthrow RuntimeException
), тогда как ошибки Дуриана позволяют применять политику на лету с помощью большого набора утилитарных методов. Спасибо, что поделились этим , @NedTwigg !.Пример использования:
источник
Я думаю, что
Errors
класс Дуриана сочетает в себе многие плюсы различных предложений выше.Чтобы включить Дуриан в ваш проект, вы можете:
com.diffplug.durian:durian:3.3.0
Throwing.java
иErrors.java
источник
Это не относится к Java 8. Вы пытаетесь скомпилировать что-то эквивалентное:
источник
Отказ от ответственности: я еще не использовал Java 8, только читал об этом.
Function<String, Integer>
не бросаетIOException
, так что вы не можете поместить в него какой-либо кодthrows IOException
. Если вы вызываете метод, который ожидает aFunction<String, Integer>
, то лямбда, которую вы передаете этому методу, не может генерироватьIOException
, точка. Вы можете написать лямбда-код следующим образом (я думаю, что это синтаксис лямбды, не уверен):Или, если метод, которому вы передаете лямбду, является тем, который вы написали сами, вы можете определить новый функциональный интерфейс и использовать его в качестве типа параметра вместо
Function<String, Integer>
:источник
@FunctionalInterface
аннотация не обязательна, чтобы ее можно было использовать для лямбд. Рекомендуется для проверки работоспособности.Если вы не против использовать стороннюю библиотеку ( Vavr ), вы можете написать
Он также имеет так называемую монаду Try, которая обрабатывает ошибки:
Пожалуйста, прочитайте больше здесь .
Отказ от ответственности: я создатель Vavr.
источник
Вы можете использовать Unthrow обертку
или
источник
Однако вы можете создать свой собственный FunctionalInterface, который выдает, как показано ниже.
затем реализуйте его, используя Lambdas или ссылки, как показано ниже.
источник
Вы можете.
Расширяя @marcg
UtilException
и добавляя generic,<E extends Exception>
где это необходимо: таким образом, компилятор снова заставит вас добавлять предложения throw, и все будет так, как если бы вы могли изначально генерировать отмеченные исключения в потоках java 8.источник
У меня была эта проблема с Class.forName и Class.newInstance внутри лямбды, поэтому я просто сделал:
Внутри лямбды вместо вызова Class.forName («myClass»). NewInstance () я просто вызвал uncheckedNewInstanceForName («myClass»)
источник
Другое решение, использующее обертку Function, - вернуть либо экземпляр обертки вашего результата, скажем, Success, если все прошло хорошо, либо экземпляр, скажем, Failure.
Некоторый код, чтобы уточнить вещи:
Простой вариант использования:
источник
Эта проблема беспокоила меня также; Вот почему я создал этот проект .
С этим вы можете сделать:
Всего имеется 39 интерфейсов, определенных JDK, которые имеют такой
Throwing
эквивалент; все они@FunctionalInterface
используются в потоках (база,Stream
но такжеIntStream
,LongStream
иDoubleStream
).И так как каждый из них расширяет свой не бросающий аналог, вы можете напрямую использовать их и в лямбдах:
Поведение по умолчанию состоит в том, что, когда ваша бросающая лямбда генерирует проверенное исключение,
ThrownByLambdaException
генерируется проверенное исключение в качестве причины. Поэтому вы можете уловить это и получить причину.Другие функции также доступны.
источник
@FunctionalInterface public interface SupplierWithCE<T, X extends Exception> { T get() throws X; }
- таким образом, пользователь не должен перехватыватьThrowable
, а вместо этого проверять исключение.ThrownByLambdaException
, у вас будет исходное исключение в качестве причины (или вы можете использоватьrethrow(...).as(MyRuntimeException.class)
)Throwing.runnable()
и другие, всегда с возможностью цепочкиЗдесь уже опубликовано много отличных отзывов. Просто пытаюсь решить проблему с другой точки зрения. Это только мои 2 цента, пожалуйста, поправьте меня, если я где-то не прав.
Предложение Throws в FunctionalInterface не очень хорошая идея
Я думаю, что это, вероятно, не очень хорошая идея, чтобы принудительно генерировать IOException по следующим причинам.
Это выглядит как анти-паттерн для Stream / Lambda. Вся идея заключается в том, что вызывающая сторона решит, какой код предоставить и как обработать исключение. Во многих сценариях IOException может быть неприменимо для клиента. Например, если клиент получает значение из кеша / памяти вместо фактического ввода-вывода.
Кроме того, обработка исключений в потоках становится действительно отвратительной. Например, вот мой код будет выглядеть, если я использую ваш API
Ужасно не так ли? Более того, как я уже упоминал в моем первом пункте, метод doSomeOperation может вызывать или не вызывать IOException (в зависимости от реализации клиента / вызывающей стороны), но из-за предложения throws в вашем методе FunctionalInterface мне всегда приходится писать Попробуйте поймать.
Что мне делать, если я действительно знаю, что этот API выдает IOException
Тогда, вероятно, мы путаем FunctionalInterface с типичными интерфейсами. Если вы знаете, что этот API вызовет IOException, то, скорее всего, вам также известно некоторое поведение по умолчанию / абстрактное поведение. Я думаю, что вы должны определить интерфейс и развернуть свою библиотеку (с реализацией по умолчанию / абстрактно) следующим образом
Но проблема try-catch все еще существует для клиента. Если я использую ваш API в потоке, мне все равно нужно обрабатывать IOException в отвратительном блоке try-catch.
Предоставьте API, дружественный к потоку по умолчанию, следующим образом
Метод по умолчанию принимает в качестве аргумента объект-потребитель, который будет отвечать за обработку исключения. Теперь, с точки зрения клиента, код будет выглядеть так
Хорошо, верно? Конечно, вместо Exception :: printStackTrace можно использовать регистратор или другую логику обработки.
Вы также можете предоставить метод, аналогичный https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html#exceptionally-java.util.function.Function- . Это означает, что вы можете предоставить другой метод, который будет содержать исключение из предыдущего вызова метода. Недостатком является то, что вы теперь делаете свои API-интерфейсы с состоянием, что означает, что вам нужно управлять безопасностью потоков, что в конечном итоге приведет к снижению производительности. Просто вариант, чтобы рассмотреть, хотя.
источник
Stream
вызвал Исключение. Таким образом, мне нравится идея иметь обработчик исключений и фильтровать недопустимые результаты. Обратите внимание, что ваш MyAmazingAPI является по сутиFunctionalInterface
(поэтому вы можете добавить аннотацию @FunctionalInterface). Также вы можете использовать значение по умолчанию вместо использованияOptional.empty()
.Идиома подлый бросок позволяет обойти
CheckedException
лямбда-выражение. УпаковкаCheckedException
вRuntimeException
не подходит для строгой обработки ошибок.Его можно использовать как
Consumer
функцию, используемую в коллекции Java.Вот простая и улучшенная версия ответа Jib .
Это просто переворачивает лямбду в перебрасывании . Это делает
CheckedException
отбрасывание любого,Exception
что было брошено в вашу лямбду.Найдите полный код и юнит-тесты здесь .
источник
Вы можете использовать ET для этого. ET - это небольшая библиотека Java 8 для преобразования / перевода исключений.
С ET это выглядит так:
ExceptionTranslator
экземпляры являются потокобезопасными и могут совместно использоваться несколькими компонентами. Вы можете настроить более конкретные правила преобразования исключений (напримерFooCheckedException -> BarRuntimeException
), если хотите. Если другие правила недоступны, отмеченные исключения автоматически преобразуются вRuntimeException
.(Отказ от ответственности: я автор ET)
источник
То, что я делаю, это позволяет пользователю дать значение, которое он на самом деле хочет в случае исключения. Так что я что-то похож на это
И тогда это можно назвать как:
источник
Если вы не возражаете против использования сторонней библиотеки, с Cylops-реагировать , библиотекой, в которую я добавляю , вы можете использовать API FluentFunctions для написания
ofChecked принимает jOOλ CheckedFunction и возвращает смягченную ссылку обратно в стандартную (непроверенную) JDK java.util.function.Function.
В качестве альтернативы вы можете продолжать работать с захваченной функцией через API FluentFunctions!
Например, чтобы выполнить свой метод, повторить его до 5 раз и записать его статус, вы можете написать
источник
По умолчанию функция Java 8 не позволяет генерировать исключения, и, как предлагается в нескольких ответах, есть много способов ее достижения, один из них:
Определить как:
И добавить
throws
илиtry/catch
то же исключение в вызывающем методе.источник
Создайте пользовательский тип возвращаемого значения, который будет распространять проверенное исключение. Это альтернатива созданию нового интерфейса, который отражает существующий функциональный интерфейс с небольшой модификацией «исключения исключения» в методе функционального интерфейса.
Определение
CheckedValueSupplier
CheckedValue
Применение
В чем дело?
Создается единственный функциональный интерфейс, который выдает проверенное исключение (
CheckedValueSupplier
). Это будет единственный функциональный интерфейс, который позволяет проверять исключения. Все остальные функциональные интерфейсы будут использоватьCheckedValueSupplier
для переноса любой код, который выдает проверенное исключение.CheckedValue
Класс будет содержать результат выполнения какой - либо логики, генерирующий проверяемое исключение. Это предотвращает распространение проверенного исключения до точки, в которой код пытается получить доступ к значению, которое экземплярCheckedValue
.Проблемы с этим подходом.
CheckedValue#get()
будет вызвано.Потребитель и др.
Некоторые функциональные интерфейсы (
Consumer
например) должны обрабатываться другим способом, поскольку они не обеспечивают возвращаемое значение.Функция вместо потребителя
Один из подходов заключается в использовании функции вместо потребителя, которая применяется при обработке потоков.
обострять
Кроме того, вы всегда можете перейти к
RuntimeException
. Существуют и другие ответы, которые охватывают эскалацию проверенного исключения изнутри aConsumer
.Не потреблять
Просто избегайте функциональных интерфейсов и используйте петлю for в хорошем стиле.
источник
Я использую перегруженную служебную функцию,
unchecked()
которая называется несколько вариантов использования.НЕКОТОРЫЕ ПРИМЕРНЫЕ ИСПОЛЬЗОВАНИЯ
СЛУЖБА ПОДДЕРЖКИ
источник
Некоторые из предложенных решений используют общий аргумент E для передачи типа исключения, которое выдается.
Сделайте еще один шаг, и вместо того, чтобы передавать тип исключения, передайте Consumer типа исключения, как в ...
Вы можете создать несколько вариантов многократного использования,
Consumer<Exception>
которые будут соответствовать общим потребностям обработки вашего приложения.источник
Я сделаю что-то общее:
Применение:
источник
Используйте
Jool Library
или говоритеjOOλ library
отJOOQ
. Он не только предоставляет непроверенные интерфейсы для обработки исключений, но также предоставляет классу Seq множество полезных методов.Кроме того, он содержит функциональные интерфейсы с 16 параметрами. Кроме того, он предоставляет класс Tuple, который используется в различных сценариях.
Jool Git Link
В частности, поиск в библиотеке для
org.jooq.lambda.fi.util.function
пакета. Он содержит все интерфейсы из Java-8 с предварительно установленным флажком. См. Ниже для справки: -источник
Я являюсь автором крошечной библиотеки с некоторой общей магией, позволяющей создавать любые исключения Java в любом месте без необходимости их перехвата или переноса
RuntimeException
.Применение:
unchecked(() -> methodThrowingCheckedException())
источник: https://github.com/qoomon/unchecked-exceptions-java
источник
источник
<code>/<code>
:)