Java Optional.orElseThrow签名说明

时间:2018-06-21 20:53:35

标签: java generics optional parameterized-constructor

出于好奇,我查看了Optional类方法orElseThrow,但对其签名感到困惑。我不明白为什么必须这样声明它。因此,我用原始orElseThrow方法的副本和简化后的变体进行了实验:

public class Main<T> {

    //This is original signature of Optional.orElseThrow method 
    public  <X extends Throwable> T orElseThrow(Supplier<? extends X> exceptionSupplier) throws X{

            throw exceptionSupplier.get();
    }

    //This is my attempt to simplify it but it doesn't work without try-catch block
    public T orElseThrow2(Supplier<Throwable> exceptionSupplier) throws Throwable{

        throw exceptionSupplier.get();
    }

    public static void main(String[] args){
        Main<Object> m = new Main<Object>();

            m.orElseThrow(() -> new RuntimeException("ha")); //no warnings/errors shown

            m.orElseThrow2(() -> new RuntimeException("sad")); //"Unhandled exception: java.lang.Throwable"
}
  1. 为什么没有try-catch块就不能接受我的方法?

  2. 为什么即使原始方法抛出Throwable对象,也可以像原始方法一样扩展 try-catch并不需要Throwable块?

2 个答案:

答案 0 :(得分:3)

  1. 因为所有编译器都知道您的方法是抛出Throwable。由于Throwable因此可能是一个检查异常,因此您不得不在throws子句中声明它或捕获它。

  2. 因为编译器知道该方法抛出X,所以泛型类型X推断为RuntimeException() -> new RuntimeException("ha")Supplier<RuntimeException>。根据定义,运行时异常是未经检查的异常,不需要在throws子句中声明。

答案 1 :(得分:1)

要进一步阐明步骤:

具有通用异常(引发X)可以提高灵活性。

如果在使用第一个签名时返回检查异常:

m.orElseThrow(() -> new Exception("ha"));

编译器也会给出错误(未处理的异常),因为它知道可能会抛出某些检查过的异常。但是,提供RuntimeException会使编译器有迹象表明它是未经检查的异常。

另一方面,在您的自定义方法中,您要确保它始终会抛出Throwable,这需要进行处理。