为什么我必须在提供 lambda 参数时捕获异常?
Why must I catch exceptions when providing lambda argument?
考虑以下示例:
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
(也没有任何其他 checked 异常)。
在Java中,有checked vs unchecked异常(未检查的异常是那些继承自RuntimeException
).必须处理已检查的异常,方法是在 catch
块中捕获它们,或者通过声明方法 throws
该异常。
如果 Supplier.get
的签名是:
T get() throws Exception:
代码可以正常编译。
尝试抛出 RuntimeException
而不是 Exception
并且代码可以正常编译。
编辑: 根据 Peter Lawrey 在评论中的建议,如果您确实需要从 lambda 表达式中抛出检查异常,您可以使用例如Callable
,其唯一一个方法的签名如下:
T call() throws Exception;
您只需要将 Callable
传递给您的 display
方法而不是 Supplier
.
考虑以下示例:
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
(也没有任何其他 checked 异常)。
在Java中,有checked vs unchecked异常(未检查的异常是那些继承自RuntimeException
).必须处理已检查的异常,方法是在 catch
块中捕获它们,或者通过声明方法 throws
该异常。
如果 Supplier.get
的签名是:
T get() throws Exception:
代码可以正常编译。
尝试抛出 RuntimeException
而不是 Exception
并且代码可以正常编译。
编辑: 根据 Peter Lawrey 在评论中的建议,如果您确实需要从 lambda 表达式中抛出检查异常,您可以使用例如Callable
,其唯一一个方法的签名如下:
T call() throws Exception;
您只需要将 Callable
传递给您的 display
方法而不是 Supplier
.