我正在努力学习基本的Java知识和不同类型的“可抛出异常”,请问有人能告诉我异常和错误(Errors)之间的区别吗?
错误不应该被捕获或处理(除非在极少数情况下)。异常处理的核心是异常。Javadoc很好地解释了这一点:
Error是Throwable的一个子类,表示合理应用程序不应尝试捕获的严重问题。大多数此类错误都是异常情况。
看一下几个Error
的子类,以及它们的JavaDoc注释:
AnnotationFormatError
- 当注释解析器尝试从类文件中读取注释并确定注释格式不正确时抛出。AssertionError
- 表示断言失败时引发。LinkageError
- LinkageError的子类表示一个类对另一个类有一些依赖关系;但是,在前者编译之后,后者类发生了不兼容的更改。VirtualMachineError
- 指示Java虚拟机已损坏或已耗尽其继续运行所需的资源。实际上,Throwable
有三个重要的子类:
Error
- 出现严重问题,大多数应用程序应该崩溃而不是尝试处理问题,RuntimeException
)- 很多时候是编程错误,例如NullPointerException
或非法参数。应用程序有时可以处理或从这个Throwable
类别中恢复--或者至少在线程的run()
方法中捕获它,记录投诉并继续运行。FileNotFoundException
和TimeoutException
...这张由@georgios-gousios制作的展示Java异常层次结构的幻灯片简明地解释了在Java中错误和异常之间的区别。
错误通常表示您的应用程序已经结束了。通常无法恢复,并应导致VM退出。除了可能记录或显示适当的消息之前退出之外,不应该捕获它们。
例如: OutOfMemoryError - 你几乎不能做任何事情,因为你的程序无法再运行。
异常通常是可恢复的,即使不可恢复,它们通常只意味着尝试的操作失败,但您的程序仍然可以继续运行。
例如: IllegalArgumentException - 向方法传递了无效数据,因此方法调用失败,但它不会影响未来的操作。
这些只是简单的示例,关于异常还有大量的信息可供了解。
java.lang.Error
类型。java.lang.StackOverflowError
,java.lang.OutOfMemoryError
java.lang.Exception
类型。try-catch
块处理异常来从异常中恢复。SQLException
,IOException
未检查的异常:ArrayIndexOutOfBoundException
,ClassCastException
,NullPointerException
更多阅读:http://javaconceptoftheday.com/difference-between-error-vs-exception-in-java/
Error
类的描述非常清晰:
引用自Java自己对类
Error
是Throwable
的子类,表示严重问题,合理的应用程序不应该尝试捕获。大多数此类错误都是异常情况。虽然ThreadDeath
错误是“正常”条件,但它也是Error
的子类,因为大多数应用程序不应该尝试捕获它。方法不需要在其 throws 子句中声明可能在方法执行期间但未被捕获的
Error
子类,因为这些错误是不应该发生的异常情况。
Error
的文档的说明。Error
,除非您有充分的理由这样做。(例如,为了防止Servlet耗尽内存或类似问题导致Web服务器实现崩溃。)Exception
只是像其他现代语言中的普通异常一样。您可以在Java API文档或任何在线或离线资源中找到详细描述。Java.lang.Exception和java.lang.Error之间有几个相似点和不同点。
相似点:
首先,这两个类都扩展了java.lang.Throwable
,因此继承了许多常用于处理错误的方法,例如:getMessage
、getStackTrace
、printStackTrace
等。
其次,作为java.lang.Throwable
的子类,它们都继承了以下属性:
Throwable本身及其任何子类(包括java.lang.Error
)都可以使用throws
关键字在方法异常列表中声明。对于java.lang.Exception
及其子类,此类声明是必需的;对于java.lang.Throwable
、java.lang.Error
和java.lang.RuntimeException
及其子类,此类声明是可选的。
只有java.lang.Throwable
及其子类允许在catch
子句中使用。
只有java.lang.Throwable
及其子类可以与关键字throw
一起使用。
由此得出的结论是,java.lang.Error
和java.lang.Exception
都可以在方法头中声明,在catch
子句中使用,可以与关键字throw
一起使用。
不同点:
首先 - 概念上的区别:java.lang.Error
设计为由JVM抛出,指示严重问题并意图停止程序执行而不是被捕获(但像其他任何java.lang.Throwable
后继者一样,这是可能的)。
来自javadoc关于java.lang.Error
的描述:
…表示严重问题,合理的应用程序不应尝试捕获它。
相反,java.lang.Exception
旨在表示程序员可以处理而不终止程序执行的预期错误。
来自javadoc关于java.lang.Exception
的描述:
…表示一个合理的应用程序可能想要捕获的条件。
java.lang.Error
和java.lang.Exception
之间的差异是前者被视为编译时异常检查的未受检查异常。因此,抛出代码java.lang.Error
或其子类不需要在方法头中声明此错误。当抛出java.lang.Exception
时,需要在方法头中声明。错误主要是由应用程序运行的环境引起的。例如,当JVM内存不足时会发生OutOfMemoryError,堆栈溢出时会发生StackOverflowError。
异常主要由应用程序自身引起。例如,当应用程序尝试访问空对象时会发生NullPointerException,当应用程序尝试转换不兼容的类类型时会发生ClassCastException。
在我看来,错误是指可能导致应用程序失败且不应该被处理的问题。而异常则是指可能导致结果不可预测但可以从中恢复的问题。
例如:
如果一个程序已经耗尽了内存,那么这就是一个错误,因为应用程序无法继续执行。然而,如果一个程序接受了错误的输入类型,那么这就是一个异常,因为程序可以处理它并重定向以接收正确的输入类型。
这里有一个来自Java API的相当不错的总结,它解释了Error和Exception的含义:
Error是Throwable的一个子类,表示严重问题,合理的应用程序不应该尝试捕获。大多数此类错误都是异常情况。ThreadDeath错误虽然是“正常”情况,但也是Error的一个子类,因为大多数应用程序不应该尝试捕获它。
方法不需要在其throws子句中声明可能在方法执行期间但未被捕获的任何Error子类,因为这些错误是不应该发生的异常情况。
另一方面,对于Exceptions,Java API说:
Exception类及其子类是Throwable的一种形式,表示合理的应用程序可能想要捕获的条件。
Unchecked exceptions != RuntimeExceptions
,而是Unchecked exceptions = RuntimeExceptions + Errors
。这引出了一个问题:Error是异常吗?,但这就是他们写的。以下是其中一个例子:https://docs.oracle.com/javase/tutorial/essential/exceptions/runtime.html。 - ROMANIA_engineer