有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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()”时,它显然不会执行

为什么编译器会拒绝它?我认为用try来包围它是很合理的。。。只在实际调用lambda时捕获


共 (1) 个答案

  1. # 1 楼答案

    这是因为Supplier功能接口的签名:

    T get();
    

    如您所见,方法get没有声明为抛出Exception(也没有任何其他选中的异常)

    在Java中,有选中的未选中的异常(未选中的异常是从RuntimeException继承的异常)。必须通过在catch块中捕获已检查的异常,或通过声明方法throws处理该异常来处理已检查的异常

    如果Supplier.get的签名是:

    T get() throws Exception:
    

    代码可以很好地编译

    尝试抛出RuntimeException而不是Exception,代码将可以很好地编译


    编辑:根据Peter Lawrey在评论中的建议,如果确实需要从lambda表达式中抛出选中的异常,可以使用例如^{},其唯一一个方法的签名如下:

    T call() throws Exception;
    

    只需要将Callable传递给display方法,而不是Supplier