[英]How to throw an exception inside a Lambda?
如何在 lambda 中抛出异常,例如在 Optional 的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();
}
尽管在您的问题中没有明确提到,但我将假设您打算从ifPresentOrElse
抛出一个已检查的异常。
首先,您应该尝试理解为什么不能抛出异常。 Consumer
接口与Runnable
,只有一个抽象方法,这使其成为@FunctionalInterface
。 从文档:
请注意,可以使用 lambda 表达式、方法引用或构造函数引用创建函数式接口的实例。
这是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
类,它们可以抛出异常(因为您在它们的方法签名中声明了它们)。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());
}
解决方案是使用Project Lombok :
并使用SneakyThrows
注释包装此函数的方法,如下所示:
@SneakyThrows
void method() {
try {
foo.bar(baz).ifPresentOrElse(theBar -> {
throw()
}, () -> { response.set(notFound()); }
} catch(CustomException e) {
somethingImportantWhenExceptionIsThrown();
}
}
您可以使用 apache commons-lang3 库来做到这一点。
https:\/\/commons.apache.org\/proper\/commons-lang\/javadocs\/api-release\/org\/apache\/commons\/lang3\/function\/Failable.html<\/a>
Optional.of(obj).ifPresentOrElse(Failable.asConsumer(theBar -> {
throw new Exception();
}), () -> {});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.