异常和错误之间的区别

203

我正在努力学习基本的Java知识和不同类型的“可抛出异常”,请问有人能告诉我异常和错误(Errors)之间的区别吗?

11个回答

197

错误不应该被捕获或处理(除非在极少数情况下)。异常处理的核心是异常。Javadoc很好地解释了这一点:

Error是Throwable的一个子类,表示合理应用程序不应尝试捕获的严重问题。大多数此类错误都是异常情况。

看一下几个Error的子类,以及它们的JavaDoc注释:

  • AnnotationFormatError - 当注释解析器尝试从类文件中读取注释并确定注释格式不正确时抛出。
  • AssertionError - 表示断言失败时引发。
  • LinkageError - LinkageError的子类表示一个类对另一个类有一些依赖关系;但是,在前者编译之后,后者类发生了不兼容的更改。
  • VirtualMachineError - 指示Java虚拟机已损坏或已耗尽其继续运行所需的资源。

实际上,Throwable有三个重要的子类:

  • Error - 出现严重问题,大多数应用程序应该崩溃而不是尝试处理问题,
  • Unchecked Exception(也称为RuntimeException)- 很多时候是编程错误,例如NullPointerException或非法参数。应用程序有时可以处理或从这个Throwable类别中恢复--或者至少在线程的run()方法中捕获它,记录投诉并继续运行。
  • Checked Exception(又称为其他所有异常) - 应用程序应该能够捕获并有意义地处理其余部分,例如FileNotFoundExceptionTimeoutException...

13
Oracle表示Unchecked exceptions != RuntimeExceptions,而是Unchecked exceptions = RuntimeExceptions + Errors。这引出了一个问题:Error是异常吗?,但这就是他们写的。以下是其中一个例子:https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html。 - ROMANIA_engineer
1
未解之谜是RuntimeException和Error在本质上有何不同?两者都是未检查的,其他方面相等。 - Pacerier

51

这张由@georgios-gousios制作的展示Java异常层次结构的幻灯片简明地解释了在Java中错误和异常之间的区别。

Java Exception Hierarchy


7
我很想看到有人从NullPointerException中恢复过来:D:D:D。 - Ignacio Soler Garcia
3
它是可以的,而且甚至有意义(另一个问题是它是否好)。通常情况下,您会首先检查对象是否存在,然后调用方法或使用字段。但是,您可以尝试捕获NPE而不是检查存在性。并记录一条相关信息的日志,然后继续执行。 - Gangnus
@Gangnus:没有意义。请记住,异常会跳过代码的某些部分,并且是报告错误而不是正常操作的一种方式。 - Ignacio Soler Garcia

20

错误通常表示您的应用程序已经结束了。通常无法恢复,并应导致VM退出。除了可能记录或显示适当的消息之前退出之外,不应该捕获它们。

例如: OutOfMemoryError - 你几乎不能做任何事情,因为你的程序无法再运行。

异常通常是可恢复的,即使不可恢复,它们通常只意味着尝试的操作失败,但您的程序仍然可以继续运行。

例如: IllegalArgumentException - 向方法传递了无效数据,因此方法调用失败,但它不会影响未来的操作。

这些只是简单的示例,关于异常还有大量的信息可供了解。


以 https://examples.javacodegeeks.com/java-basics/exceptions/java-lang-illegalargumentexception-how-to-solve-illegal-argument-exception/ 为例。IllegalArgumentException 是运行时异常,而非错误。https://docs.oracle.com/javase/7/docs/api/java/lang/IllegalArgumentException.html - Gangnus

15

错误(Errors) -

  1. Java中的错误属于java.lang.Error类型。
  2. 所有Java中的错误都是未经检查的类型。
  3. 错误会在运行时发生,编译器不会知道。
  4. 无法从错误中恢复。
  5. 错误大多由应用程序运行的环境引起。
  6. 示例:java.lang.StackOverflowErrorjava.lang.OutOfMemoryError

异常(Exceptions) -

  1. Java中的异常属于java.lang.Exception类型。
  2. 异常包括已检查和未经检查的类型。
  3. 编译器知道已检查的异常,但不知道未检查的异常,因为它们发生在运行时。
  4. 可以通过使用try-catch块处理异常来从异常中恢复。
  5. 异常主要由应用程序自身引起。
  6. 示例:已检查的异常:SQLExceptionIOException 未检查的异常:ArrayIndexOutOfBoundExceptionClassCastExceptionNullPointerException

更多阅读:http://javaconceptoftheday.com/difference-between-error-vs-exception-in-java/ http://javaconceptoftheday.com/wp-content/uploads/2015/04/ErrorVsException.png


9

Sun 最好表达了

错误是Throwable的一个子类, 它表示严重问题,合理的应用程序不应该尝试捕捉它。


5
Error类的描述非常清晰:

ErrorThrowable的子类,表示严重问题,合理的应用程序不应该尝试捕获。大多数此类错误都是异常情况。虽然ThreadDeath错误是“正常”条件,但它也是Error的子类,因为大多数应用程序不应该尝试捕获它。

方法不需要在其 throws 子句中声明可能在方法执行期间但未被捕获的Error子类,因为这些错误是不应该发生的异常情况。

引用自Java自己对Error的文档的说明。
简而言之,您不应该捕获Error,除非您有充分的理由这样做。(例如,为了防止Servlet耗尽内存或类似问题导致Web服务器实现崩溃。)
另一方面,Exception只是像其他现代语言中的普通异常一样。您可以在Java API文档或任何在线或离线资源中找到详细描述。

3

Java.lang.Exception和java.lang.Error之间有几个相似点和不同点。

相似点:

  • 首先,这两个类都扩展了java.lang.Throwable,因此继承了许多常用于处理错误的方法,例如:getMessagegetStackTraceprintStackTrace等。

  • 其次,作为java.lang.Throwable的子类,它们都继承了以下属性:

    • Throwable本身及其任何子类(包括java.lang.Error)都可以使用throws关键字在方法异常列表中声明。对于java.lang.Exception及其子类,此类声明是必需的;对于java.lang.Throwablejava.lang.Errorjava.lang.RuntimeException及其子类,此类声明是可选的。

    • 只有java.lang.Throwable及其子类允许在catch子句中使用。

    • 只有java.lang.Throwable及其子类可以与关键字throw一起使用。

由此得出的结论是,java.lang.Errorjava.lang.Exception都可以在方法头中声明,在catch子句中使用,可以与关键字throw一起使用。

不同点:

  • 首先 - 概念上的区别:java.lang.Error 设计为由JVM抛出,指示严重问题并意图停止程序执行而不是被捕获(但像其他任何java.lang.Throwable后继者一样,这是可能的)。

    来自javadoc关于java.lang.Error的描述:

    …表示严重问题,合理的应用程序不应尝试捕获它。

    相反,java.lang.Exception旨在表示程序员可以处理而不终止程序执行的预期错误。

    来自javadoc关于java.lang.Exception的描述:

    …表示一个合理的应用程序可能想要捕获的条件。

  • 第二个java.lang.Errorjava.lang.Exception之间的差异是前者被视为编译时异常检查的未受检查异常。因此,抛出代码java.lang.Error或其子类不需要在方法头中声明此错误。当抛出java.lang.Exception时,需要在方法头中声明。

Throwable及其后续类图(省略了属性和方法)。 enter image description here


1

错误主要是由应用程序运行的环境引起的。例如,当JVM内存不足时会发生OutOfMemoryError,堆栈溢出时会发生StackOverflowError。

异常主要由应用程序自身引起。例如,当应用程序尝试访问空对象时会发生NullPointerException,当应用程序尝试转换不兼容的类类型时会发生ClassCastException。

来源:Java中错误与异常的区别


“错误主要是由应用程序运行的环境引起的”,而“异常主要是由应用程序本身引起的”。完美! - ADJ

1

在我看来,错误是指可能导致应用程序失败且不应该被处理的问题。而异常则是指可能导致结果不可预测但可以从中恢复的问题。

例如:

如果一个程序已经耗尽了内存,那么这就是一个错误,因为应用程序无法继续执行。然而,如果一个程序接受了错误的输入类型,那么这就是一个异常,因为程序可以处理它并重定向以接收正确的输入类型。


0

这里有一个来自Java API的相当不错的总结,它解释了Error和Exception的含义:

Error是Throwable的一个子类,表示严重问题,合理的应用程序不应该尝试捕获。大多数此类错误都是异常情况。ThreadDeath错误虽然是“正常”情况,但也是Error的一个子类,因为大多数应用程序不应该尝试捕获它。

方法不需要在其throws子句中声明可能在方法执行期间但未被捕获的任何Error子类,因为这些错误是不应该发生的异常情况。

另一方面,对于Exceptions,Java API说:

Exception类及其子类是Throwable的一种形式,表示合理的应用程序可能想要捕获的条件。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接