【问题标题】:Is there a use case where Error is manually thrown?是否存在手动抛出错误的用例?
【发布时间】:2021-02-19 15:20:36
【问题描述】:

我知道这是一个非常菜鸟的问题。

我一直在浏览博客和文章,试图了解 Java 中使用错误的原因和位置,但没有运气。在实践中,我从未见过错误被使用,并且在异常情况下会发生错误。

这些只是供内部库使用吗?可以在程序中手动抛出吗?可能,我们不应该这样做,但我们可以吗?

【问题讨论】:

    标签: java exception error-handling


    【解决方案1】:

    如果你愿意,可以扔掉它们。这是合法的 java 代码并且运行良好:

    class Example {
      public static void main(String[] args) {
        throw new Error();
      }
    }
    

    就像运行时异常一样,你不需要声明你这样做(假设你写了throw new IOException();,那么除非你把它变成…main(String[] args) throws IOException,否则它不会编译。运行时异常和错误不需要明确列出,但是。

    有一个 ton 的代码可以捕获所有异常。这些通常是“入口点控制器”——启动应用程序的东西。 Java 本身会启动您的 main(并将捕获任何 main 抛出的内容,并将其转换为命令行上的漂亮打印),但 Web 服务器、应用程序服务器和插件运行器都做类似的事情:Web 服务器将接收 HTTP 请求,如图找出应该调用哪个处理程序代码来处理它,(有人编写了 Web 框架 - 但您编写了该处理程序),然后将捕获该处理程序之外的任何和所有异常,然后提供 500 错误并记录有关此事件的大量信息。您的public void doGet() 或您在 Web 处理程序中必须使用的东西是一个 入口点,而网络框架调用它的点称为 入口点控制器。 p>

    大多数入口点控制器都有一个合法的:

    try {
        invokeEntryPoint();
    } catch (Exception e) {
        // deal with it...
        // web frameworks would log the request, for example.
    }
    

    许多控制器捕获错误,这是运行时异常和错误之间的实际主要区别:RuntimeExceptions 和 Errors 不需要在 throws 子句中说明,但 RuntimeExceptions 是常规的捕获,尤其是被入口点控制器捕获,而错误通常不会,因此它们会导致更彻底的堆栈展开:它“关闭”到进程的更深处。使用网络服务器,它可能会关闭整个网络服务器。这可能是一个好主意,例如,如果由于 VM 的磁盘损坏或系统内存不足而破坏了 JVM 不变量,那么这可能是比仅捕获错误、日志记录更好的选择(日志记录本身可以然后由于内存问题而不可能),然后继续。让操作系统看门狗自动重启服务器。

    这就是务实的区别。

    那么,你应该什么时候抛出Error?很少见,但如果您检测到违反有关您的应用程序的基本假设,即错误或配置错误(相对于正常操作期间可能发生的事件,例如用户上传的图像文件),这是有保证的这是无效的)。这种情况的常见情况是,如果您使用YourClass.class.getResource("states.txt") 来检索一些数据文件,这些数据文件与您的类文件一样多是您应用程序的一部分:如果丢失,那么您的安装已损坏,并且Error 很有道理:

    try (InputStream in = AbichandanisApp.class.getResource("splash_screen.png")) {
        if (in == null) throw new Error("Resource missing: splash_screen.png");
        renderSplashScreen(new Image(in));
    }
    

    这是正确使用 throwing Error 的示例。

    【讨论】:

    • 知道了!错误基本上允许你偏离你不想发生的事情的执行!如果我错了,请纠正我...此外,损坏的 JVM 也是入口点控制器不应捕获错误的一个很好的理由。
    • 接受这个作为答案... :)
    • 好吧,任何条带的 throwable 都可以用来“偏离正常执行”,但是,是的,错误特别适用于本应不可能的情况,但如果它们确实发生了,你想要尽可能多地关闭它 - 根据定义,那么,你真的不想发生的事情。这就是故障安全系统的生命周期:)
    【解决方案2】:

    当然可以(构造函数是公开的)。

    如果您的代码中出现“合理的应用程序不应尝试捕获的严重问题”,您应该这样做。

    见: https://docs.oracle.com/javase/7/docs/api/java/lang/Error.html

    【讨论】:

    • 您能否提供一个需要这样做的示例? bcz 我知道只有在绝对需要时才会抛出错误。
    • @Abichandani 也许如果你构建一个依赖于系统不被篡改的库,你可以抛出一个SystemHasBeenTamperedWithError
    • 有道理!同样,有助于处理没有人愿意发生的情况,我理解这是公开错误的唯一目的。如果我错了,请纠正我!
    猜你喜欢
    • 2018-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-23
    • 2012-05-28
    • 1970-01-01
    • 2022-01-23
    相关资源
    最近更新 更多