【问题标题】:Why must I catch exceptions when providing lambda argument?为什么在提供 lambda 参数时必须捕获异常?
【发布时间】:2020-10-09 14:51:32
【问题描述】:

考虑以下示例:

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 包围它是很合理的。

【问题讨论】:

标签: java lambda functional-interface


【解决方案1】:

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

T get();

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

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

如果Supplier.get的签名是:

T get() throws Exception:

代码可以正常编译。

尝试抛出RuntimeException 而不是Exception,代码将编译正常。


编辑:根据 Peter Lawrey 在 cmets 中的建议,如果您确实需要从 lambda 表达式中抛出检查异常,您可以使用例如Callable,只有一个方法的签名如下:

T call() throws Exception;

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

【讨论】:

  • 例如Callable 确实抛出了 Exception
  • 嗨@Peter,感谢您的建议,我将在Callable 中提供一个示例
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-19
  • 1970-01-01
  • 2018-04-27
  • 1970-01-01
  • 1970-01-01
  • 2012-09-25
相关资源
最近更新 更多