运行时/已检查/未检查/错误/exception之间的差异

什么是运行时exception以及什么是选中/未选中的exception以及错误/exception之间的区别。为什么这么多类型? 相反,Java可能只是遵循一个简单的设计(只是尝试/捕获所有类型)来处理程序中的exception情况?

除了所有例外之外,Throwable是最重要的。 在Throwable下面你有错误和exception。 在Exception下面你有RuntimeException。

Java有两种类型的例外 – 已检查和未选中。 检查的exception由编译器强制执行(您必须在throws子句中声明它们并最终捕获它们)。 对throws子句中的捕获或声明不强制执行未经检查的exception。

(有争议的部分答案)

存在Throwable,因此所有exception类型都有父级。 你永远不应该声明你扔掉了Throwable并且永远不会抓住它(除非你真的真的知道你在做什么)。

存在错误表示运行时环境存在问题,程序可能无法从中恢复,例如格式错误的类文件或内存不足的VM。 除非你真的知道自己在做什么,否则不应该发现错误。

exception作为所有非程序员错误的根存在(请参阅RuntimeException以获取此exception),例如由于磁盘已满而无法创建文件。 你不应该抛出,抛出或捕获exception。 如果您必须捕获exception,请确保您知道自己在做什么。

存在RuntimeException以指示所有程序员错误,例如超过数组末尾或调用null对象上的方法。 这些是你应该修复的东西,这样它们就不会抛出exception – 这表明你,程序员,搞砸了代码。 除非你知道自己在做什么,否则你不应该抓住这些。

由于我是一名新的Java开发人员,因此在区分和处理不同类型的exception时也遇到了一些困难。 这就是为什么我在这个主题上做了一个简短的说明,每当我感到困惑时,我都要经历它。 这里是Throwable类层次结构的图像:
可抛出的类层次结构

[图片由JavaTpoint提供 ]。

这里要记住三个关键类: ThrowableExceptionError 。 在这些类中, Exception可以分为两种类型:“Checked Exception”和“Unchecked Exception”。

检查exception:

  • 这些是扩展Throwable的类,除了RuntimeExceptionError
  • 它们也称为编译时exception,因为它们在编译时被检查,这意味着编译器强制我们使用try/catch处理它们,或者在函数签名中指示它throws它们并强制我们在调用者中处理它们。
  • 它们是程序可恢复的问题,这些问题是由代码控制之外的意外情况引起的(例如数据库关闭,文件I / O错误,错误输入等)。
  • 示例: IOExceptionSQLException等。

未经检查的例外情况:

  • 扩展RuntimeException的类称为未经检查的exception。
  • 未经检查的exception不会在编译时检查,而是在运行时检查,因此名称。
  • 它们也是可编程恢复的问题,但与检查exception不同,它们是由代码流或配置中的错误引起的。
  • 示例: ArithmeticExceptionNullPointerExceptionArrayIndexOutOfBoundsException等。
  • 由于它们是编程错误,因此可以通过良好/明智的编码来避免它们。 例如,“除以零”会产生ArithmeticException ,可以通过对除数进行简单检查来避免。 类似地,我们可以通过简单地检查引用来避免NullPointerExceptionif (object != null)或甚至使用更好的技术 。

错误:

  • Error是指try/catch未处理的无法恢复的情况。
  • 示例: OutOfMemoryErrorVirtualMachineErrorAssertionError等。

为什么这么多类型?

除了Stephen C的回答我想说:exception处理在Java中是一个相对昂贵的操作。 我们不应该将所有exception情况放在try/catch块中。 过度使用try/catch可能会妨碍程序性能。

最后,应尽可能以编程方式处理Exception 。 另一方面,我们无法处理Error ,因此这可能是为什么有许多类型的exception的一些逻辑原因。

TofuBeer的答案清楚地解释了exception类的含义。

为什么这么多类型? 相反,Java可能只是遵循一个简单的设计(只是尝试/捕获所有类型)来处理程序中的exception情况?

为什么? 因为他们是必要的! 如果没有这4个类,按广义类别处理exception将是不切实际的。

  • 如果没有Error类,你会如何捕获“所有致命的JVM错误”?
  • 如果没有Exception类,您将如何捕获“不是JVM致命错误的所有exception”?
  • 如果没有RuntimeException类,您将如何捕获“所有未经检查的exception”?

运行时exception为您提供了避免捕获,声明exception的灵活性。

  • 错误(由VM引发,不应该被捕获或处理)
    1. VM错误
    2. 断言错误
    3. 链接错误……等等
  • 运行时/取消选中exception(编程错误,不应该被捕获或处理)
    1. 空指针exception
    2. ArrayIndexOutOfBoundException
    3. IllegalArgumentException ……等等
  • 检查例外(任何其他情况,预计应用程序将被捕获或处理)
    1. IOExceptionexception
    2. FileNotFoundExceptionexception
    3. SQLException …等等

已检查和未检查的exception之间的区别:

我们在已检查和未检查的exception之间存在许多差异,但所有差异都源于一次基本考虑,即exception是否可由编译器解决。

要记住的要点是:

[1]已检查exception表示编译器已检查exception 。 这意味着编译器要求try-catch块或throws关键字处理此类exception。

[2]未经检查的exception是编译器不提供任何授权的exception,因为开发人员可以通过编码/编程来解析它们,因为控制流是可控的,如ArithmeticException,NullPointerException ArrayIndexOutOfBoundsException,IllegalArgumentException等。

我将其称为“Exception-Identity-Test” ,您可以从java doc中获取任何随机exception,只需问一个问题。 “嘿,例外! 你能以编程方式解决吗?“

如果exception表示YES,那么它是未经检查的exception,因为这可以通过代码更改或解决某些计算错误等来解决。

另一方面,如果Exception表示No,那么这是Checked Exception,因为在检查Exception控制流程离开了我们的代码,就像有人更改数据库密码或有人拔掉网络电缆,连接超时(ConnectException),找不到某些资源( FileNotFoundException,ClassNotFound),SQLException,InvocatonTargetException等。这些不能通过编程解决