供应商<X>和供应商<之间有什么区别?扩展 X>

问题描述

在“可选”源代码中,我找到了这个函数

public <X extends Throwable> T orElseThrow(supplier<? extends X> exceptionsupplier) throws X {
    if (value != null) {
        return value;
    } else {
        throw exceptionsupplier.get();
    }
}

我的问题是,如果我将功能更改为此,它看起来工作相同

public <X extends Throwable> T orElseThrow(supplier<X> exceptionsupplier) throws X {
    if (value != null) {
        return value;
    } else {
        throw exceptionsupplier.get();
    }
}

有人知道原因吗?

解决方法

考虑这个方法:

void example() throws IOException {
  throw new FileNotFoundException();
}

这声明它抛出一般的IOException,但具体抛出一个更具体的异常,FileNotFoundException

orElseThrow 相同:通过接受上限供应商,它可以抛出更具体的异常类型。

差异在大多数情况下无关紧要,因为您始终可以捕获/throws 更通用的异常类型。我认为它可能会产生影响的一种情况是当您接受 Supplier 作为参数时:

<X extends IOException> void example(Supplier<? extends X> exceptionSupplier)
    throws IOException {  // Note IOException,not X.
  Optional.empty().orElseThrow(exceptionSupplier);
}

您可以使用以下任一供应商作为参数来调用它:

Supplier<IOException> s1 = IOException::new;
Supplier<FileNotFoundIOException> s2 = FileNotFoundIOException::new;

但是如果没有 Supplier<? extends X> 的上限,你就不能做后者。