throws x extends Exception 方法签名

2022-09-01 22:56:09

阅读可选的JavaDoc,我碰到了一个奇怪的方法签名;我这辈子从未见过:

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)
                                throws X extends Throwable

乍一看,我想知道通用异常是如何可能的,因为你不能这样做(这里这里)。经过再三考虑,这开始变得有意义,因为它只是为了绑定...但是供应商本身在泛型之前确切地知道它应该是什么类型。<X extends Throwable>Supplier

但第二行击中了我:

  • throws X是完全泛型异常类型。

然后:

  • X extends Throwable到底是什么意思?
    • X已绑定在方法签名中。
  • 这是否会以任何方式解决通用异常限制?
  • 为什么不只是 ,因为其余的将被类型擦除?throws Throwable

还有一个,没有直接相关的问题:

  • 是否要求将此方法捕获为 或按提供的 类型捕获;因为它无法在运行时进行检查?catch(Throwable t)Supplier

答案 1

像对待你读过的任何其他通用代码一样对待它。

以下是我在Java 8源代码中看到的正式签名:

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X
  • X的上限为 。这在以后会很重要。Throwable
  • 我们返回一个绑定到 的类型的类型TOptionalT
  • 我们期望 a 具有通配符上限SupplierX
  • 我们抛出(这是有效的,因为其上限为 )。这在 JLS 8.4.6 中指定;只要被视为 的子类型,其声明在这里是有效和合法的。XXThrowableXThrowable

有一个关于Javadoc具有误导性的开放错误。在这种情况下,最好信任源代码而不是文档,直到宣布 Bug 得到修复。

至于为什么我们使用代替 :保证在最上限被绑定。如果你想要一个更具体的(运行时、检查或),那么仅仅抛出不会给你这种灵活性。throws Xthrows ThrowableXThrowableThrowableErrorThrowable

对于您的最后一个问题:

是否需要在 catch(Throwable t) 子句中捕获此方法?

链下的某些东西必须处理异常,无论是块还是JVM本身。理想情况下,人们希望创建一个绑定到一个最能传达其需求的例外。您不必(可能也不应该)为这种情况创建一个;如果您的类型绑定到需要处理的特定异常,那么最好将其用作链中的后身。try...catchSuppliercatch(Throwable t)Suppliercatch


答案 2

Javadoc的方法签名与源代码不同。根据b132消息来源

public <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier)
              throws X {  // Added by me: See? No X extends Throwable
    if (value != null) {
        return value;
    } else {
        throw exceptionSupplier.get();
    }
}

证实:这是Javadoc生成的一个问题。作为测试,我创建了一个新项目,并为以下类生成了Javadoc:

package com.stackoverflow.test;

public class TestJavadoc {
    public static <X extends Throwable> void doSomething() throws X {

    }
}

这是生成的 Javadoc:

Javadoc Screenshot

双确认:对于此类,有一个关于 Javadoc 的开放 bug