当前位置: 首页 > 知识库问答 >
问题:

为什么Java 8类型推断不考虑重载选择中Lambdas抛出的异常?

钮善
2023-03-14

我有一个关于Java8关于lambda及其相关异常签名的推断的问题。

如果我定义某个方法foo:

public static <T> void foo(Supplier<T> supplier) {
    //some logic
    ...
}

然后,我得到了一个很好和简洁的语义:在大多数情况下,可以为给定的t编写foo(()->getTheT());。但是,在本例中,如果我的getthet操作声明它的抛出异常,那么我的foo方法将不再编译:get的Supplier方法签名不会抛出异常。

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类型不明确(可能无法在Supplier和ThrowingSupplier之间解决),这会引起一些问题。使用foo((ThrowingSupplier)(()->operationWhichThrows()));进行显式强制转换可以工作,但它会消除所需语法的大部分简洁性。

任何信息或资源,任何人可以指出我将同样非常感谢,因为我只是不太确定在哪里寻找更多的信息关于这件事。

谢谢!

共有1个答案

禹智渊
2023-03-14

如果这让您感觉好一点,那么在JSR-335设计过程中确实仔细考虑了这个主题。

问题不是“为什么它不能”,而是“为什么我们选择不能”。当我们发现多个可能适用的重载时,我们当然可以选择推测性地将lambda体属性到每组签名下,并剪除lambda体未能进行类型检查的那些候选项。

然而,我们的结论是,这样做可能弊大于利;例如,它意味着,在此规则下,对方法主体的微小更改可能会导致某些方法重载选择决策在用户不打算这样做的情况下静默更改。最后,我们得出结论,利用方法体中存在的错误来丢弃一个可能适用的候选项会造成更多的混乱,而不是好处,特别是考虑到有一个简单而安全的变通方法--提供一个目标类型(target-type)。我们觉得这里的可靠性和可预测性超过了最佳的简洁性。

 类似资料:
  • 主要内容:1 Java8 类型推断的介绍,2 Java8 类型推断的案例1,3 Java8 类型推断的案例21 Java8 类型推断的介绍 类型推断是Java的一项功能,它使编译器可以查看每个方法调用和相应的声明以确定参数的类型。 Java在Java 8中提供了类型推断的改进版本。 1.1 Java8以前 在下面的声明中,我们在一侧提到了arraylist的类型。这种方法是在Java 7中引入的。在这里,您可以将第二面留为<>,并且编译器将通过引用变量的类型来推断其类型。 1.2 Java8以后

  • 下面是我的代码。当我运行它时,我在线程“main”java.lang.IndexOutOfBoundsException:Index:3、Size:2中得到异常,而不是我的异常消息。谁能解释一下我做错了什么,为什么会这样?谢谢!

  • 问题内容: 我正在使用Java 的本地实现,该实现具有如下方法: 这两种方法可以编译并正常工作: 此方法无法编译: 错误: (我已经修剪了包限定符,以使错误更易读) 我可以通过指定类型进行编译: 但是为什么我需要呢?以及如何避免此代码混乱? 问题答案: 此代码应该起作用。 它在最新的JDK 1.8.0_121上编译。 无法在JDK 1.8.0-51上编译。 这意味着它在此版本的JDK中很可能是一个

  • 我们应该在什么时候选择抛出一个异常? 我们可以在try catch中捕获此异常。 在哪种情况下,我们选择使用投掷而不是立即接球?是否与设计模式相关?

  • 我目前正在研究Typescript中的重载。 假设我有一个重载的函数: 要么调用函数时没有参数,要么调用函数时有两个参数(foo和bar)。根据vscode的智能感知,结果变量具有布尔|未定义的类型。 为什么即使我已经测试了参数,仍然可以?如果存在,那么类型推断不应该预测也存在吗?

  • 我是jUnit和mockito的新手。对于虚空的嘲弄是如何发挥作用的,我完全感到困惑。在这里,如果名称是“hello”,则函数抛出一个异常。但当我测试它时,它并没有抛出异常... 测试 }