请考虑以下代码:

public class Main {
    public static void main(String[] args)
             // throws Exception // line 1 
    {
        Optional empty1 = Optional.empty(); // line 2
        Optional<Object> empty2 = Optional.empty(); // line 3

        Optional.empty().orElseThrow(() -> new Exception("Empty optional")); // line 4
        empty1.orElseThrow(() -> new Exception("Empty optional")); // line 5
        empty2.orElseThrow(() -> new Exception("Empty optional")); // line 6
    }

}
  • 当第1行被注释时,第4、5、6行都报告编译时错误:

    • 4号线和6号线:Unhandled exception: java.lang.Exception
    • 第5行:Unhandled exception: java.lang.Throwable 这让我觉得,像第6行一样,第4行使用类型参数<Object>来调用,但是抛出的确切异常有什么不同呢?
  • 如果未注释第1行,则只有第5行报告编译时错误:Unhandled exception: java.lang.Throwable.把1号线改成throws Throwable号线就可以解决了.为什么抛出Exception不足以让第5行解决编译时错误?

推荐答案

不同之处在于Java中使用了原始类型.OrElseThrow的方法签名为:

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

因此,对于第2行和第5行的情况,您具有:

Optional empty1 = Optional.empty(); // line 2
empty1.orElseThrow(() -> new Exception("Empty optional")); // line 5

orElseThrow以上的签名 case 中,编译器没有提供T类型,即使它有X类型,也会生成原始调用.它将用可抛的上界替换X,T将是Object.结果是:

public Object orElseThrow(Supplier exceptionSupplier) throws Throwable
                                                             ^^^^^^^^^

因此,编译器报告:

error: unreported exception Throwable

以下情况:

Optional.empty().orElseThrow(() -> new Exception("Empty optional")); // line 4

更有趣的是,这里没有指定显式类型,但是编译器报告抛出错误Exception.所以这与之前的情况不同.您必须再次查看所用函数的签名,在本例中为Optional.Empty():

public static<T> Optional<T> empty()
             ^^^ ~~~ type inference

重要的部分是<T>,这表明它将从所附的上下文中推断其类型T.在line 4中,编译器无法推断类型,而使用Object类型.我相信JLS,它是这样说的:

https://docs.oracle.com/javase/specs/jls/se10/html/jls-18.html#jls-18.1.3

如果PL没有类型边界,则绑定的αL<;:对象将出现在集合中.

在甲骨文教程中也有:

https://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html

编译器需要类型参数T的值,因此它启动 使用值对象.因此,调用 Collections.emptyList返回List<;Object>;类型的值.

重要的是,在line 4中处理的不是第2行和第5行那样的原始类型,而是泛型类型(泛型类型TObject),因此当调用orElseThrow时,其签名是

public Object orElseThrow(Supplier exceptionSupplier) throws Exception

这两种泛型类型TX都是已知的,因此会生成泛型函数调用,这最终会在您的示例中导致以下编译器错误:

错误:未上报异常异常;

现在,第3行和第6行显式使用泛型类型对象,这使得orElseThrow的签名与前面一样:

public Object orElseThrow(Supplier exceptionSupplier) throws Exception

这给出了相同的错误:

错误:未上报异常异常;

Java相关问答推荐

如何在Javascript中设置文本区域圆角的样式

如何在返回bigint []值的子查询中使用any?

@org.springframework.beans.factory.annotation.Autowired(required=true)-注入点有以下注释:-SpringBoot

基本时态运算的ISO-8601周数据表示法

扩展到弹出窗口宽度的JavaFX文本字段

JavaFX如何在MeshView中修复多个立方体?

当Volatile关键字真的是必要的时候?

对于亚洲/香港,使用ResolverStyle.STRICT的LocalDate.parse返回意外结果

使用多个RemoteDatabase对象的一个线程

S,要对Java复制构造函数深度克隆所有属性进行单元测试,最可靠的方法是什么?

与IntArray相比,ArrayList<;Int>;对于大量元素的性能极差

Android Java:已设置但未读取SharedPreferences

在缺少字段时使用Jackson With Options生成Optional.Empty()

在WHILE()循环初始化部分中声明和初始化变量的Java语法?

使用同步方法中的新线程调用同步方法

如何在特定关键字后提取与模式匹配的多个值?

如何在单元测试中获得我的装饰Mapstruct映射器的实例?

Eureka客户端无法使用用户/通行证注册到Eureka服务器

Maven创建带有特定类的Spring Boot jar和普通jar

如何在Java上为循环数组从synchronized迁移到ReentrantLock