运行时/检查/非检查/错误/异常的区别

26

什么是运行时异常?什么是已检查/未检查异常?错误和异常之间的区别是什么?为什么会有这么多类型?相反,Java 可以简单地遵循一个简单的设计(只尝试捕获所有类型)来处理程序中的异常情况吗?


你有没有阅读过Sun Java Tutorials关于异常的课程?那可能是一个不错的开始。 - Isaac Truett
8个回答

42

由于我是一名新的Java开发人员,我也遇到了区分和处理不同类型异常的一些困难。这就是为什么我在这个主题上做了一个简短的笔记,每当我感到困惑时,我就会浏览它。以下是带有Throwable类层次结构图像的内容:
Throwable Class Hierarchy

[图片来源:JavaTpoint]。

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

Checked Exception:

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

Unchecked Exception:

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

错误:

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

为什么有这么多类型?

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

总之,应尽可能以编程方式处理Exception。另一方面,我们无法处理Error,因此这可能是有许多类型异常的某些逻辑原因。


2
+1 给这张漂亮的图片。顺便说一句,一个 Error 不可捕获并不是严格正确的。没有人阻止你编写 try { sometching(); } catch(Error e) { },但实际上这样做是一个坏主意(有关详细信息,请参见 @TofuBeer 的答案)。 - Qw3ry

38

Throwable是所有异常的顶级父类。在Throwable下面有Error和Exception,在Exception下面有RuntimeException。

Java有两种类型的异常 - checked异常和unchecked异常。编译器强制执行checked异常(你必须在throws子句中声明它们并最终捕获它们)。未强制执行unchecked异常以用于捕获或在throws子句中声明。

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

Error表示运行时环境出现问题,这些问题可能使你的程序无法恢复,比如格式错误的类文件或虚拟机内存耗尽。除非你真的知道自己在做什么,否则不要捕获Error。

Exception作为所有非程序员错误的根源(参见RuntimeException以了解其"例外"情况),比如因磁盘空间满而无法创建文件。不应该抛出、throws或捕获Exception。如果必须捕获Exception,请确保你知道自己在做什么。

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


4

TofuBeer的回答清晰地解释了异常类的含义。

为什么有这么多类型?Java为什么不遵循一个简单的设计(只需尝试/捕获所有类型)来处理程序中的异常情况呢?

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

  • 如果没有Error类,你如何捕获“所有致命的JVM错误”?
  • 如果没有Exception类,你如何捕获“所有非JVM致命错误的异常”?
  • 如果没有RuntimeException类,你如何捕获“所有未经检查的异常”?

1
  • 错误(VM抛出的,不应该被捕获或处理)
    1. VM错误
    2. 断言错误
    3. 链接错误...等等
  • 运行时/未检查异常(编程错误,不应该被捕获或处理)
    1. 空指针异常
    2. 数组索引越界异常
    3. 非法参数异常...等等
  • 检查异常(其他所有内容,期望应用程序被捕获或处理)
    1. IO异常
    2. 文件未找到异常
    3. SQL异常...等等

0

Checked和Unchecked异常的区别:

Checked和Unchecked异常有很多区别,但所有的区别都源于一个基本考虑,即编译器是否可以解决异常

需要记住的要点是:

[1] Checked异常意味着编译器检查异常。这意味着编译器强制要求使用try-catch块或throws关键字来处理此类异常。

[2] Unchecked异常是指编译器不提供任何强制规定的异常,因为开发人员可以通过编码/编程来解决它们,控制流是可控的,例如ArithmeticException、NullPointerException ArrayIndexOutOfBoundsException、IllegalArgumentException等。

我称之为“异常身份测试”,您可以从Java文档中随机选择任何异常,并问它一个问题。“嘿,异常!你能通过编程解决吗?”

如果异常回答YES,那么它就是一个Unchecked异常,因为可以通过更改代码或解决某些计算错误等方式来解决它。

另一方面,如果异常信息显示“”,那么这就是已检查异常。在已检查异常中,控制流会跳出我们的代码,例如如果有人更改了数据库密码或拔掉了网络电缆,连接超时(ConnectException),某些资源未找到(FileNotFoundException、ClassNotFound),SQLException,InvocatonTargetException等等。这些异常无法通过编程解决。

0

这篇文章以清晰简洁的方式总结了CheckedUnchecked异常。

  • Checked Exceptions: 已检查异常是在编译时可以检测、识别和检查的异常。如果代码块抛出了一个已检查异常,那么方法必须处理该异常或使用throws关键字指定该异常。

    • 示例:

      public void testDB() throws ClassNotFoundException, SQLException
      {
          Class.forName("com.mysql.jdbc.Driver");
          System.out.println("Driver Loaded");
          Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/selenium","root","root");
          System.out.println("Connected to MySQL DB");
      }
      
    • 我们需要使用throws指定异常列表或使用try-catch{}块。我在下面的程序中演示了throws的用法。

  • Unchecked Exceptions: 未检查异常不会在编译时进行检查。Java异常在ErrorRuntimeException类下是未经检查的异常,而在throwable下的所有其他内容都是已检查的。

摘要:如果可以合理地期望客户端从异常中恢复,将其设置为已检查的异常。如果客户端无法从异常中恢复,则将其设置为未经检查的异常。

-1

运行时异常提供了灵活性,避免了捕获和声明异常的繁琐过程。


3
好的,我会尽力进行翻译:似乎不捕获异常,直接让它终止线程是可以接受的解决方案。 - Bombe
1
通常认为自己生成 RuntimeException 是一个不好的主意®。请小心使用,不要仅仅将其作为一种捷径。 - user4229245

-2
Exceptions are two types in java:

1. **Checked Exception: The exceptions which are checked by compiler. 

例如:当您正在执行文件操作时,编译器会要求您通过try-catch块或throws关键字处理IOException。
2. Unchecked Exception: The exceptions which are not checked by compiler at run time. 

例如:如果您在没有创建对象的情况下对其执行操作,则会出现NullPointerException。

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