我最近一直在阅读许多关于异常的文章,我有一个问题是否应该捕获未经检查的异常。我已经读到,如果您希望您的应用程序从错误中恢复,请使用检查异常。但是,如果您无法处理已检查的异常,则可以将其包装到另一个已检查的异常中,以便将其传递给另一层;例如,你包装了一个SqlException
,或者你抛出了一个未经检查的异常。但是,是否应该捕获未经检查的异常?未经检查的异常是否是您不检查的理想编程错误?它们应该从您的应用程序中冒出来吗?
是否应该捕获并处理未经检查的异常?
答案是,这取决于:
-
这取决于例外是什么。
-
这取决于引发异常的原因。 是"意料之中"吗? 是由于错误、错误输入还是环境问题? 还是别的什么?
-
这取决于是否有恢复的好方法。 这通常部分取决于以前的标准。
如果异常是意外的,异常的原因不确定,和/或者如果您确实捕获了异常,则没有合理的恢复策略,那么通常最好允许异常冒泡,并确保它在顶层被报告/记录。
如果异常是Error
,一般规则是您不应尝试恢复。 这包括StackOverflowError
和(特别是)OutOfMemoryError
.Error
异常表示难以(或不可能)安全恢复的问题,最佳策略是允许或导致应用程序退出。
在顶层报告/记录是什么意思?例如,您的意思是在UI层捕获它并显示对话框,记录它等吗?
我的意思是,异常及其堆栈跟踪应该写入应用程序的日志文件,以便维护人员可以查看问题的证据。 您是否也尝试向最终用户解释问题(以及如何执行此操作)是一个单独的问题。
"顶级"可能是"主"方法,子线程或可运行的"运行"方法......或未捕获的异常处理程序。 基本上,如果异常没有被捕获,它最终会"冒泡"到哪里。 详细信息将取决于应用程序的体系结构。
您应该捕获异常(选中或未选中),如果您能够以有意义的方式处理它以从问题中恢复。 如果您没有很好的方法来处理异常,通常不应捕获异常。
我见过太多的代码通过执行e.printStackTrace()
然后继续"处理"异常,就好像没有错一样。 忽略这样的问题通常只会导致以后的其他问题。
没有什么可以阻止您捕获运行时异常。
如今的趋势是使用越来越多的运行时异常,而检查的异常越来越少。Spring、Hibernate 和最新的 Java EE 规范几乎只使用运行时异常。这使得业务代码更易于阅读且不那么繁琐。
运行时异常通常根本不被捕获,或者仅在调用堆栈底部的 UI 层中捕获,以便显示错误消息,因为当发生此类异常时,这通常是您唯一可以做的事情。
Checked
和Unchecked
之间的基本区别 例外是,您需要显式处理前者或在inheritance hierarchy
中传播它,而后者则不需要这样做。
此外,CheckedException
从java.lang.Exception
扩展,而UncheckedExceptions
从不需要处理的java.lang.RuntimeException
扩展。请注意,RuntimeException
本身就是Exception
的子类。
鉴于上述所有信息,如果您handle
unchecked exception
那么它很好。它将正常工作,并且控件将转到相应的catch
块。但你不应该这样做。除非,你真的需要它,并且你有适当的方法来处理它们。
-
例如: -您应该处理一个
IllegalArgumentException
一个Unchecked Exception
. -
然后,您不应该处理以下错误: -
StackOverflowError
.因为,您不知道为什么会出现该问题,以及处理该问题的适当方法是什么。因此,只需将其留给JVM。Errors
是您无法从中恢复的Unchecked Exception
。
有关更多详细信息,请参阅以下链接: -
- http://tutorials.jenkov.com/java-exception-handling/checked-or-unchecked-exceptions.html
- http://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html
检查异常的选择通常是:如果您无法对其进行任何操作,只需将其添加到throws
,如果您无法对它做任何有用的事情,则可以将其catch
并将其转换为以原始为原因的新异常,但可以添加信息,如果可行,则对其进行catch
并对其进行处理,并且代码中的正确位置也可以对其进行处理。
未经检查的异常有点棘手。在理想世界中,它们应该指示编程/逻辑错误,并且像断言失败一样处理,而不是捕获,尤其是不吞噬。
在我看来,来自 Java 标准库或其他库的一些未经检查的异常确实应该是检查异常,但事实并非如此。在这些情况下,调用方应承认此类异常可能会通过它们,即使他们没有catch
它们。对于未经检查的异常,也可以检查异常,基本上相同的规则:如果你想对它们做点什么,就抓住它们,否则让它们冒泡。如果您正在创建一个库(即使它只是应用程序的内部),并且未经检查的异常确实是以后应该捕获的东西,那么您可能希望捕获并将其重新抛出到库代码中的已检查异常中。
通常,尽量避免引发未经检查的异常。检查输入,因此您无需catch
,如果仍然抛出异常,则它是一个错误,应该不被捕获。只有当这是唯一的或至少显然是最好的方法时,才catch
它们。
公平地说,Java库的语言是在那个时代设计的,当时IDE还没有立即抱怨缺少抛出子句并提出自动填充它们,因此通过减轻开发人员的负担,使它们不受检查可能是合理的。但是有了现代工具,真的没有任何借口。
然后,正如其他答案中提到的,您不应该捕获未经检查的异常。
你应该捕获未经检查的异常吗?
是和不是。取决于引发的异常。
未经检查的异常是否是您不检查的理想编程错误?
您可以编写一个catch
块来捕获未经检查的异常,但同样取决于您是否应该这样做。如果你这样做,那么一个错误可能会在很长一段时间内仍未解决,当它被发现时,它的大小也会改变。
它们应该从您的应用程序中冒出来吗?
如果它们发生,请尝试解决其原因(如果可能的话)。不要总是把它们catch
为硬性规定和快速规则。