为什么Java 8类型推断在重载选择时不考虑由Lambda引发的异常?
为什么Java 8类型推断在重载选择时不考虑由Lambda引发的异常?
我对Java 8中关于lambda表达式及其相关异常签名的推断有一个问题。
如果我定义一个名为foo的方法:
public staticvoid foo(Supplier supplier) { //一些逻辑 ... }
那么对于给定的foo(() -> getTheT());
。然而,在这个例子中,如果我的getTheT
操作声明它throws Exception
,那么接受Supplier的foo方法将无法编译通过:Supplier的get
方法签名不会抛出异常。
解决这个问题的一种方法是重载foo方法,接受两种选项,重载的定义如下:
public staticvoid foo(ThrowingSupplier supplier) { //与另一个方法相同的逻辑 ... }
其中ThrowingSupplier定义为:
public interface ThrowingSupplier{ public T get() throws Exception; }
这样,我们有了一个会抛出异常的Supplier类型和一个不会抛出异常的Supplier类型。所期望的语法应该是这样的:
foo(() -> operationWhichDoesntThrow()); //不会抛出异常,由Supplier处理 foo(() -> operationWhichThrows()); //会抛出异常,由ThrowingSupplier处理
然而,这会导致lambda类型模糊不清(无法解析Supplier和ThrowingSupplier之间的区别)。通过显式强制转换如foo((ThrowingSupplier)(() -> operationWhichThrows()));
可以解决问题,但这会使期望的语法大部分简洁性消失。
我猜测根本问题是:如果Java编译器能够解析出一个lambda在只使用Supplier时不兼容的原因是它抛出一个异常,为什么它不能利用相同的信息推断出二次类型推断情况下lambda的类型呢?
如果有任何信息或资源可以指导我,我将非常感激,因为我不太确定在哪里寻找更多相关信息。
谢谢!