【问题标题】:Should unchecked exceptions be caught and dealt with?是否应该捕获和处理未经检查的异常?
【发布时间】:2012-11-06 12:45:20
【问题描述】:

我最近一直在阅读许多关于异常的帖子,我有一个问题,是否应该捕获未经检查的异常。我已经读过,如果您希望您的应用程序从错误中恢复,您可以使用检查异常。但是,如果您无法处理已检查的异常,则可以将其包装到另一个已检查的异常中,以便将其传递给另一层;例如你包装一个SqlException,或者你抛出一个未经检查的异常。但是,您应该捕获未经检查的异常吗?未经检查的异常是否是您不检查的理想编程错误?他们应该从您的应用程序中冒出来吗?

【问题讨论】:

    标签: java unchecked-exception


    【解决方案1】:

    是否应该捕获和处理未经检查的异常?

    答案取决于:

    • 这取决于异常是什么。

    • 这取决于抛出异常的原因。是“预期的”吗?是因为错误、输入错误还是环境问题?还是别的什么?

    • 这取决于是否有恢复的好方法。这通常部分取决于之前的标准。

    如果异常是意料之外的,异常的原因是不确定的,和/或如果你确实捕获了异常没有健全的恢复策略,那么通常最好让异常冒泡,并确保它在顶层被报告/记录。

    如果异常是Error,一般规则是您不应该尝试恢复。这包括StackOverflowError 和(特别是)OutOfMemoryErrorError 异常表示难以(或不可能)安全恢复的问题,最好的策略是允许或导致应用程序退出。


    在顶层报告/记录是什么意思?您的意思是在 UI 层捕获它并显示一个对话框、记录它等吗?

    我的意思是应该将异常及其堆栈跟踪写入应用程序的日志文件,以便维护人员可以查看问题的证据。您是否还尝试向最终用户解释问题(以及您是如何做到的)是一个单独的问题。

    “顶级”可能是“main”方法、子线程或runnable 的“run”方法……或未捕获的异常处理程序。基本上,如果异常没有被捕获,它最终会“冒泡”到任何地方。详细信息将取决于您的应用程序的架构。

    【讨论】:

      【解决方案2】:

      如果你能以有意义的方式处理它以从问题中恢复,你应该捕获一个异常 - 已检查或未检查。如果您没有好的方法来处理异常,您通常应该捕获它。

      我已经看到太多代码通过执行e.printStackTrace() 来“处理”异常,然后继续执行,就好像没有出错一样。忽略这样的问题通常只会导致以后出现其他问题。

      【讨论】:

        【解决方案3】:

        没有什么可以阻止您捕获运行时异常。

        现在的趋势是使用越来越多的运行时异常,而越来越少的受检异常。 Spring、Hibernate 和最新的 Java EE 规范几乎完全使用运行时异常。这使业务代码更易于阅读且不那么繁琐。

        运行时异常通常根本不被捕获,或者只在调用堆栈的底部,在 UI 层中捕获,以便显示错误消息,因为这通常是你唯一可以做的事情出现这样的异常。

        【讨论】:

        • 啊,有道理,只在UI层捕获它们并显示错误。
        【解决方案4】:

        CheckedUnchecked Exception 之间的基本区别在于,您需要显式处理前者或将其传播到inheritance hierarchy,而后者则不需要。

        另外,CheckedException 扩展自 java.lang.Exception,而 UncheckedExceptions 扩展自 java.lang.RuntimeException,不需要处理。请注意,RuntimeException 本身是Exception 的子类。

        鉴于以上所有信息,如果您 handleunchecked exception 那就没问题了。它将正常工作,并且控件将转到相应的catch 块。但你不应该这样做。除非,你真的需要它并且你有适当的方法来处理它们。

        • 例如:- 您应该处理IllegalArgumentException,即 Unchecked Exception

        • 然后,您不应该处理如下错误:-StackOverflowError。因为,你不知道为什么会出现这个问题,以及什么是处理它的合适方法。所以,把它留给JVM。 Errors 是您无法恢复的 Unchecked Exception

        更多详情,请参考以下链接:-

        【讨论】:

        • 我知道这很旧,很抱歉,但我需要问一下——为什么我们需要处理 IllegalArgumentException——这是否表明程序员错误,事实上,如果我们阅读了抛出它的方法的文档,我们应该在实际传递之前确定要传递的正确参数吗?
        • 这与可能导致代码运行不良的逻辑错误有关。例如您不希望您的用户将负数传递给计算 sqrt 的方法,在这种情况下,您将在开头添加一个测试,如果找到负数,您想告知用户这一点, 可能通过抛出异常说传递的参数是非法的。
        【解决方案5】:

        检查异常的选择通常是:如果你不能做任何事情,你只需将它添加到throwscatch,如果你不能做任何有用的事情,则将其转换为以原始为原因的新异常关于它,但可以添加信息,catch 它并在可行的情况下对其进行处理,并且在您的代码中正确的位置对此进行处理。

        未经检查的异常有点棘手。在理想的世界中,它们应该指示编程/逻辑错误,并像断言失败一样被处理,不会被捕获,尤其是不会被吞没。

        在我看来,来自 Java 标准库或其他库的一些未经检查的异常确实应该是检查异常,但不是。在这些情况下,调用者应该承认这些异常可能会通过它们,即使它们没有catch 它们。对于未检查的异常也可以是检查的异常,基本相同的规则:如果你想对它们做点什么就抓住它们,否则让它们冒泡。如果您正在创建一个库(即使它只是应用程序的内部),并且未经检查的异常确实应该稍后被捕获,那么您可能希望在库代码中捕获并重新将其包装到已检查的异常中.

        一般来说,尽量避免抛出未经检查的异常。检查输入,所以你不需要catch,如果仍然抛出异常,那么这是一个错误,应该不被捕获。只有catch他们,如果这是唯一的或至少显然是最好的方法。

        公平地说,Java 库是在这个时代设计的,当时 IDE 还没有立即抱怨缺少 throws 子句并提供自动填充它们,因此不检查它们可能是通过减轻开发商。但是使用现代工具,真的没有任何借口。

        然后,正如其他答案中提到的那样,您应该捕获未经检查的异常。

        【讨论】:

        • 在大多数情况下,“承认某些异常可能会通过”是错误的做法;不幸的是,它也是处理受检异常的最简单方法。问题是,如果foo 调用bar,并且bar 抛出一个检查异常moofoo 没有准备好处理,那么调用者现在将要处理两个问题:( 1) moo 类型的异常将被抛出但未被捕获; (2)foo的执行会在一个意想不到的地方被中断。在许多情况下,后一个问题实际上可能是更严重的问题......
        • ...但是异常系统没有为foo 提供方便的方法来表明这一点。 foo 在语义上更简洁的模式是捕捉意外的已检查异常并将它们作为未检查异常抛出,但这很尴尬;此外,如果出现FileNotFoundException,最好将其报告为FileNotFoundException,而不是UnexpectedException
        • @supercat 我不确定你的意思,但“意外的检查异常”对我来说听起来很矛盾。如果foo 的程序员没有考虑到它调用的方法的任何检查异常,那就是一个错误。我所说的“帐户”是指,例如,对 IO 使用“try-with-resources”等。
        • 如果某个方法调用不可能抛出某个异常,除非数据结构损坏到无法修复或该方法严重违反了它的约定,那么围绕该异常的错误处理代码可能没有多大用处。例如,假设一个方法应该基于“BitmapSourceInfo”对象创建一个位图对象,该对象可以提供文件名或像素数据数组。如果源信息对象可能提供文件名,那么该方法应该会抛出IOException。如果调用者创建了一个BitmapSourceInfo 对象...
        • ...但是,包含像素数据数组,并且 LoadBitmap 方法承诺在数组中提供位图数据时不会引发异常,不应期望调用者干净地处理方法抛出的IOException。此外,即使调用 LoadBitMap 的代码预计可能会因其他原因抛出 IOException,但在假设从数组复制数据时抛出 IOException 并不代表调用者期望的条件,因此不应该t percolate up as 这种类型。
        【解决方案6】:

        你应该捕获未经检查的异常吗?

        是和否。取决于抛出什么异常。

        未检查的异常是您不检查的理想编程错误吗?

        您可以编写一个catch 块来捕获未经检查的异常,但再次取决于您是否应该。如果你这样做了,那么一个 bug 可能会在很长一段时间内仍未解决,并且当它被发现时,它的大小也会发生变化。

        他们应该从你的应用程序中冒出来吗?

        如果它们发生,请尝试解决它们的原因(如果可能的话)。不要catch他们总是作为硬性规定。

        【讨论】:

        • InputFormatException from a Scanner 未选中,并不罕见,应该恢复。
        • 这同样适用于任何其他IOException
        • 你的意思是IllegalArgumentException
        • 建议一种在不触发IllegarArgumentExceptions 的情况下使用Scanner 的方法。
        • IOException 绝对是一个检查异常。
        猜你喜欢
        • 2018-11-02
        • 1970-01-01
        • 2010-11-08
        • 1970-01-01
        • 2017-11-25
        • 1970-01-01
        • 2010-09-10
        • 1970-01-01
        相关资源
        最近更新 更多