【发布时间】:2015-09-01 03:29:16
【问题描述】:
我有一个关于 lambda 及其相关异常签名的 Java 8 推理的问题。
如果我定义一些方法 foo:
public static <T> void foo(Supplier<T> supplier) {
//some logic
...
}
然后我得到了能够在大多数情况下为给定的T 编写foo(() -> getTheT()); 的简洁明了的语义。但是,在此示例中,如果我的 getTheT 操作声明它为 throws Exception,则采用 Supplier 的 foo 方法不再编译:get 的 Supplier 方法签名不会引发异常。
似乎解决这个问题的一个不错的方法是重载 foo 以接受任一选项,重载定义为:
public static <T> void foo(ThrowingSupplier<T> supplier) {
//same logic as other one
...
}
ThrowingSupplier 定义为
public interface ThrowingSupplier<T> {
public T get() throws Exception;
}
通过这种方式,我们有一种供应商类型会引发异常,而另一种则不会。所需的语法是这样的:
foo(() -> operationWhichDoesntThrow()); //Doesn't throw, handled by Supplier
foo(() -> operationWhichThrows()); //Does throw, handled by ThrowingSupplier
但是,由于 lambda 类型不明确(可能无法在供应商和 ThrowingSupplier 之间解决),这会导致问题。像 foo((ThrowingSupplier)(() -> operationWhichThrows())); 那样进行显式转换会起作用,但它会消除所需语法的大部分简洁性。
我猜潜在的问题是:如果 Java 编译器能够解决我的一个 lambda 表达式不兼容的事实,因为它在仅限供应商的情况下抛出异常,为什么它不能使用相同的在辅助类型推断案例中推导出 lambda 类型的信息?
任何人都可以向我指出的任何信息或资源同样将不胜感激,因为我不太确定在哪里可以找到有关此事的更多信息。
谢谢!
【问题讨论】:
-
你的问题和我的很相似:stackoverflow.com/questions/14039995/…
-
当然请注意,接口方法的实现不需要抛出异常,即使该接口中的声明被声明为抛出异常。因此,对于 lambda,不仅仅是抛出的 lambda “应该”被确定使用相应的方法,而是非抛出的 lambda 应该传递给哪个方法的问题?即,
() -> nonThrowingOperation可以是任一Supplier或ThrowingSupplier。
标签: java exception lambda java-8 type-inference