首页 > 解决方案 > 为什么在提供 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 包围它是非常合理的。

标签: javalambdafunctional-interface

解决方案


这是因为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


推荐阅读