为什么Java 8类型推断在重载选择时不考虑由Lambda引发的异常?

15 浏览
0 Comments

为什么Java 8类型推断在重载选择时不考虑由Lambda引发的异常?

我对Java 8中关于lambda表达式及其相关异常签名的推断有一个问题。

如果我定义一个名为foo的方法:

public static  void foo(Supplier supplier) {
    //一些逻辑
    ...
}

那么对于给定的,我可以以简洁明了的方式编写foo(() -> getTheT());。然而,在这个例子中,如果我的getTheT操作声明它throws Exception,那么接受Supplier的foo方法将无法编译通过:Supplier的get方法签名不会抛出异常。

解决这个问题的一种方法是重载foo方法,接受两种选项,重载的定义如下:

public static  void 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的类型呢?

如果有任何信息或资源可以指导我,我将非常感激,因为我不太确定在哪里寻找更多相关信息。

谢谢!

0