首页 > 解决方案 > 为什么 Java 公开 Error 和 Java SE API 回调方法接受 Throwable 而不是 Exception?

问题描述

事实

  1. Java SE API 说它“表示一个合理的应用程序不应该试图捕捉的严重问题”Error的类型;还有“错误是不应该发生的异常情况”
  2. JLS 11.1.3“异步异常”说VirtualMachineError这是“Java 虚拟机中的内部错误或资源限制,阻止实现 Java 编程语言的语义

解释

不仅规范明确建议不要捕获Errors,而且还说如果VirtualMachineError发生,则不能保证语言语义不变。看来反对Thread.stop/的论点ThreadDeath至少也可以应用于任何VirtualMachineError。由于允许延迟解析,对于 : 也是如此LinkageError:没有代码期望它或防范它,所以当它发生时,它可能会导致像ThreadDeathor一样破坏对象的状态VirtualMachineError

以上似乎(对我而言)足以决定没有可靠的方法来处理Errors。我看到的唯一方法是Thread.UncaughtExceptionHandler调用System.exit/Runtime.halt并且可能会Error在终止 VM 之前尝试记录 (记录尝试可能会简单地失败,而另一个记录尝试可能会Error因原始记录尝试而失败,如果原始记录尝试是 则尤其明显ErrorOutOfMemoryError

问题

  1. 鉴于 anError表示不应该发生的异常情况并且应用程序不应该尝试捕获它,那么Error在 Java SE API 中完全公开类型而不是总是通过终止 VM 而不将它们暴露给应用程序来处理错误的充分理由是什么?
  2. 为什么(几乎?)Java SE API 中的所有回调方法,例如,、、、accept ,java.nio.channels.CompletionHandler.failed其中包括,而不是accept ?实际上,接受的回调并不比捕获 an的代码好(并且完成此类回调的代码必须捕获 an才能传递它,从而违反了类的建议)。这样的回调迫使用户要么 CompletionStage.exceptionallyFlow.Subscriber.onErrorThrowableErrorExceptionThrowableErrorErrorError
    • 还传播Throwable它只是将处理Errora 延迟到以后的时间,并导致更多代码在处理之前运行,从而增加了抛出另一个的机会Error(同样,对于 a 来说很明显OutOfMemoryError)。
    • 将 s包裹ErrorExceptions 中,这只是有害的,因为它Error通过使其无法以任何直接的方式检测到,从而有效地隐藏了发生的事实。
    • 处理Errors,除了终止 VM 之外,这似乎是不可能的。

标签: javaexceptioncallbackthrowable

解决方案


推荐阅读