java - 为什么在提供 lambda 参数时必须捕获异常?
问题描述
考虑以下示例:
public class LambdaArgsTest {
private static void display(Supplier<?> arg) {
try {
// this is the place where the Exception("wrong") might be thrown
// and it is in fact handled
System.out.println(arg.get());
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
display(() -> {
if(/*some condition*/) {
// this statement will be rejected due to unhandled exception
throw new Exception("wrong");
}
return "abcde";
});
}
}
问题来了:上例中的 lambda 参数是稍后将在“display()”方法中执行的对象。将参数传递给“display()”时显然不会执行。
为什么会被编译器拒绝?我认为仅在实际调用 lambda 时用 try...catch 包围它是非常合理的。
解决方案
这是因为Supplier
功能接口的签名:
T get();
如您所见,该方法get
未声明为抛出Exception
(也没有任何其他已检查 异常)。
在 Java 中,有已检查和未检查的异常(未检查的异常是继承自 的异常RuntimeException
)。必须处理已检查的异常,方法是在catch
块中捕获它们,或者通过声明该throws
异常的方法。
如果签名Supplier.get
是:
T get() throws Exception:
代码编译得很好。
尝试抛出RuntimeException
而不是,Exception
代码将编译得很好。
编辑:根据 Peter Lawrey 在评论中的建议,如果您确实需要从 lambda 表达式中抛出检查异常,您可以使用 eg Callable
,其唯一一个方法的签名如下:
T call() throws Exception;
您只需要将 a 传递Callable
给您的display
方法而不是 a Supplier
。
推荐阅读
- python - 从 MySQL 数据库中递归获取所有子项
- jquery - Any way to automatically close the hamburger menu on :focus with jQuery?
- c++ - 如何在 C++ 中实现神经网络
- django - 无法在 DRF 中捕获 31 日至 2 月的无效日期
- javascript - Vue 不会在“间接”更改表达式的值时更新 DOM
- python - 使用带有无头 chrome 的 webdriver 下载文件时出错
- node.js - mongoDb 数据库表单数据空响应
- c# - 堆栈跟踪中未显示错误行
- django - 在 get_queryset 中将表单输入设置为变量
- java - ElasticSearch 无法从单词中搜索特殊字符