运行时/已检查/未检查/错误/异常之间的区别

14 浏览
0 Comments

运行时/已检查/未检查/错误/异常之间的区别

运行时异常是什么?什么是检查异常和非检查异常?错误和异常之间的区别是什么?为什么有这么多类型的异常?相反,Java是否可以简单地遵循一个简单的设计(只需使用try/catch来处理程序中的异常情况)?

0
0 Comments

为什么会有这么多种类型?为什么Java不能简单地使用一个设计(尝试/捕捉所有类型)来处理程序中的异常情况?

为什么?因为它们是必要的!如果没有这四个类,通过广泛的类别来处理异常将是不现实的。

- 如果没有Error类,你如何捕获“所有致命的JVM错误”?

- 如果没有Exception类,你如何捕获“所有不是JVM致命错误的异常”?

- 如果没有RuntimeException类,你如何捕获“所有未经检查的异常”?

这些异常类的存在使得我们可以根据异常的类型和严重程度进行不同的处理,从而提高了程序的可靠性和可维护性。如果只有一个通用的异常类,我们将很难区分不同类型的异常,并且可能会导致错误的处理或错误的忽略异常。

对于这些异常类,我们可以使用try-catch语句来捕获并处理异常。以下是一些示例代码:

try {
    // 可能会抛出异常的代码
} catch (Error e) {
    // 处理致命的JVM错误
} catch (Exception e) {
    // 处理非致命的异常
} catch (RuntimeException e) {
    // 处理未经检查的异常
}

通过使用不同的catch块,我们可以根据异常的类型来执行不同的处理逻辑。这样可以更好地控制程序的流程,并在出现异常时采取适当的措施。

总结起来,Java中的这些异常类是为了提供更精细的异常处理机制,允许我们根据异常的类型和严重程度进行不同的处理。它们提高了程序的可靠性和可维护性,并帮助我们更好地管理和调试异常情况。

0
0 Comments

Throwable是所有异常的顶级类。

在Throwable下面有Error和Exception。

在Exception下面有RuntimeException。

Java有两种类型的异常——checked和unchecked。编译器会强制执行checked异常(必须在throws子句中声明并最终捕获)。对于unchecked异常,无需强制捕获或在throws子句中声明。

(有争议的部分)

Throwable的存在是为了成为所有异常类型的父类。除非你真的非常了解你在做什么,否则不应声明抛出Throwable并且不要捕获它。

Error用于指示运行环境出现的问题,这些问题可能是你的程序无法从中恢复的,比如格式错误的类文件或VM内存不足。除非你真的知道自己在做什么,否则不应捕获Error。

Exception用作所有非程序员错误的根类(RuntimeException是这个规则的“例外”,例如因为磁盘已满而无法创建文件)。不应该抛出、声明或捕获Exception。如果必须捕获Exception,请确保你知道自己在做什么。

RuntimeException用于指示所有程序员错误,比如超出数组的末尾或在空对象上调用方法。这些是你应该修复的错误,以避免抛出异常——它们表明你,作为程序员,弄糟了代码。同样,除非你知道自己在做什么,否则不应捕获这些异常。

对于这个问题出现的原因,可以从Java异常体系结构的设计角度来解释。Throwable作为所有异常的顶级类,提供了一个统一的父类,使得异常可以被统一处理。Error和Exception作为Throwable的子类,分别用于表示不同类型的异常。Error主要用于表示运行环境出现的严重问题,通常无法被程序处理;而Exception则用于表示一般性的异常情况。RuntimeException作为Exception的子类,用于表示程序员的错误。

为了解决这个问题,可以根据异常类型的不同采取不同的处理方式。对于Error类型的异常,一般不应该捕获和处理,而是应该让程序终止。对于Exception类型的异常,可以根据具体情况选择是否捕获和处理。对于RuntimeException类型的异常,一般应该修复代码中的错误,避免抛出异常,而不是通过捕获和处理来解决问题。需要注意的是,在捕获Exception类型的异常时,要确保自己清楚自己在做什么,避免出现潜在的问题。

了解Java异常体系结构以及各种异常类型的特点,可以更好地处理异常情况,提高程序的稳定性和健壮性。

0
0 Comments

作为一名新手Java开发者,我也面临着区分和处理不同类型异常的困难。这就是为什么我对这个主题做了一份简短的笔记,每当我感到困惑时就会浏览它。下面是关于Throwable类层次结构的图片:

Throwable Class Hierarchy

[图片由JavaTpoint提供]。

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

Checked Exception:

  • 除了RuntimeExceptionError之外,这些类都继承自Throwable
  • 它们也被称为编译时异常,因为它们在编译时进行检查,这意味着编译器强制我们要么使用try/catch处理它们,要么在函数签名中指示它们throws并强制我们在调用者中处理它们。
  • 它们是由代码无法控制的意外条件引起的可编程恢复性问题(例如,数据库关闭,文件I/O错误,错误的输入等)。
  • 例子:IOExceptionSQLException等。

Unchecked Exception:

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

Error:

  • Error指的是无法通过try/catch处理的不可恢复的情况。
  • 例子:OutOfMemoryErrorVirtualMachineErrorAssertionError等。

为什么有这么多类型?

除了Stephen C的回答外,我想说:

在Java中,异常处理是一种相对昂贵的操作。我们不应该将所有异常情况都放在try/catch块中。过多地使用try/catch可能会影响程序性能。

总之,应尽可能地通过编程方式处理Exception。另一方面,我们无法处理Error,这可能是为什么有这么多类型异常的一些逻辑原因。

对于这个很好的图片点赞。附注:严格来说,Error是可以被捕获的。没有人阻止您编写try { something(); } catch(Error e) { },但实际上这样做是个坏主意(有关详细信息,请参见的答案)。

0