#java
#java
Вопрос:
Как создать исключение внутри лямбда-выражения, например, в ifPresentOrElse
качестве необязательного?
try {
foo.bar(baz).ifPresentOrElse(theBar -> {
// A code inside here needs to throw a custom exception so the outside can handle it
// It can't throw atm, and it is an unhandled exception here
}, () -> { response.set(notFound()); }
} catch(CustomException e) {
somethingImportantWhenExceptionIsThrown();
}
Комментарии:
1. Почему бы не использовать
orElseThrow
?2. Я имею в виду, что мне нужно, чтобы оно выбрасывалось изнутри,
bar
метод для выброса.
Ответ №1:
Хотя в вашем вопросе явно не указано, я предполагаю, что вы намерены создать проверенное исключение из ifPresentOrElse
.
Во-первых, вы должны попытаться понять, почему вы не можете создать исключение. Consumer
Интерфейс имеет, как Runnable
, только один абстрактный метод, что делает его @FunctionalInterface
. Из документации:
Обратите внимание, что экземпляры функциональных интерфейсов могут быть созданы с помощью лямбда-выражений, ссылок на методы или ссылок на конструкторы.
Это сокращенная версия Consumer
интерфейса:
public interface Consumer<T> {
void accept(T t); // <-- NO throws Exception
}
В качестве альтернативы вы все еще можете использовать старый анонимный внутренний класс:
Consumer<Object> consumer = new Consumer<>() {
@Override
public void accept(Object o) { // <-- NO throws Exception
// consume
}
};
Следовательно, вы не можете создать проверенное исключение из accept
метода. Это невозможно по дизайну. Однако вы можете выбрать один из следующих вариантов:
- Не рекомендуется использовать пользовательский
ThrowingConsumer
иThrowingOptional
класс, который может генерировать исключения (поскольку вы объявляете их в сигнатурах методов). - Оберните проверенное исключение в a
RuntimeException
, которое не нужно объявлять в сигнатуре метода и, следовательно, может быть выдано. - Перепишите свой код, чтобы не использовать лямбда-выражение.
Например, для последней точки:
Optional<Bar> barOpt = foo.bar(baz);
if(bar.isPresent()) {
Bar bar = barOpt.get();
try {
// code that throws checked exception
} catch(CustomException e) {
somethingImportantWhenExceptionIsThrown();
}
} else {
response.set(notFound());
}
Комментарии:
1. 4) Используйте хак , предоставленный @quarks, но вам решать, хотите ли вы использовать Lombok.
Ответ №2:
Решением для этого является использование Project Lombok:
И аннотируйте метод, обертывающий эту функцию SneakyThrows
, как таковой:
@SneakyThrows
void method() {
try {
foo.bar(baz).ifPresentOrElse(theBar -> {
throw()
}, () -> { response.set(notFound()); }
} catch(CustomException e) {
somethingImportantWhenExceptionIsThrown();
}
}
Ответ №3:
Вы можете сделать это с помощью библиотеки apache commons-lang3.
Optional.of(obj).ifPresentOrElse(Failable.asConsumer(theBar -> {
throw new Exception();
}), () -> {});