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

Posted

技术标签:

【中文标题】运行时/已检查/未检查/错误/异常之间的差异【英文标题】:Differences between Runtime/Checked/Unchecked/Error/Exception 【发布时间】:2011-03-10 22:01:24 【问题描述】:

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

【问题讨论】:

你读过Sun Java Tutorials lesson on exceptions吗?这可能是一个不错的起点。 【参考方案1】:

由于我是一名新的Java开发人员,我在区分和处理不同类型的异常方面也遇到了一些困难。这就是为什么我在这个主题上做了一个简短的笔记,每当我感到困惑时,我都会仔细阅读。这是Throwable 类层次结构的图像:

[图片由JavaTpoint提供]。

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

检查异常:

这些是扩展 Throwable 的类,RuntimeExceptionError 除外。 它们也被称为编译时异常,因为它们在编译时被检查,这意味着编译器强迫我们要么用try/catch处理它们,要么在函数签名中指出它throws它们并强迫我们处理它们在调用者中。 它们是由代码无法控制的意外情况(例如数据库关闭、文件 I/O 错误、错误输入等)导致的可通过编程恢复的问题。 示例: IOExceptionSQLException

未经检查的异常:

扩展 RuntimeException 的类称为未经检查的异常。 未检查的异常不在编译时检查,而是在运行时检查,因此得名。 它们也是可通过编程恢复的问题,但与检查异常不同,它们是由代码流或配置中的错误引起的。 例子:ArithmeticException,NullPointerException,ArrayIndexOutOfBoundsException等 由于它们是编程错误,因此可以通过巧妙/明智的编码来避免它们。例如“除以零”产生ArithmeticException,可以通过对除数的简单检查来避免。同样,我们可以通过简单地检查引用来避免NullPointerExceptionif (object != null),甚至使用better techniques。

错误:

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

为什么会有这么多类型?

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

总之,Exceptions 应尽可能以编程方式处理。另一方面,我们无法处理Errors,因此这些可能是存在多种异常类型的一些逻辑原因。

【讨论】:

+1 为漂亮的图片。旁注:Error 无法捕获并不完全正确。没有人阻止您写try sometching(); catch(Error e) ,但这样做实际上是个坏主意(有关详细信息,请参阅@TofuBeer's answer)。【参考方案2】:

Throwable 位于所有异常的首位。 在 Throwable 下面你有错误和异常。 在 Exception 下面你有 RuntimeException。

Java 有两种类型的异常 - 已检查和未检查。已检查的异常由编译器强制执行(您必须在 throws 子句中声明它们并最终捕获它们)。在 throws 子句中捕获或声明未检查的异常不会被强制执行。

(答案有争议的部分)

Throwable 存在,因此所有异常类型都有一个父级。你永远不应该声明你抛出 Throwable 并且永远不会抓住它(除非你真的真的很清楚自己在做什么)。

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

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

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

【讨论】:

【参考方案3】:

TofuBeer's answer 清楚地解释了异常类的含义。

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

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

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

【讨论】:

【参考方案4】: 错误(由 VM 引发,不应被捕获或处理)
    虚拟机错误 断言错误 链接错误...等等
运行时/取消检查异常(编程错误,不应被捕获或处理)
    NullPointerException ArrayIndexOutOfBoundException IllegalArgumentException ... 以此类推
检查异常(其他任何情况,应捕获或处理应用程序)
    IOException FileNotFoundException SQLException ...等等

【讨论】:

【参考方案5】:

Checked 和 unchecked 异常的区别:

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

要记住的要点是:

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

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

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

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

另一方面,如果异常说 No 那么这是检查异常,因为检查异常控制流超出了我们的代码,例如如果有人更改数据库密码或有人拔掉网络电缆,连接超时(ConnectException)、一些资源未找到(FileNotFoundException、ClassNotFound)、SQLException、InvocatonTargetException等,这些无法通过编程解决

【讨论】:

【参考方案6】:

article 以简洁明了的方式总结了 CheckedUnchecked 异常。

Checked ExceptionsChecked 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 的用法。

未经检查的异常未经检查的异常在编译时不检查。 ErrorRuntimeException 类下的 Java 异常是未经检查的异常,throwable 下的所有其他内容都经过检查。

总结:如果可以合理地预期客户端会从异常中恢复,请将其设为已检查异常。如果客户端无法从异常中恢复,请将其设为未经检查的异常。

【讨论】:

【参考方案7】:

运行时异常为您提供了避免捕获、声明异常的灵活性。

【讨论】:

是的,好像不捕获异常并让它杀死线程是可以接受的解决方案。 生成您自己的RuntimeException 通常被认为是个坏主意®。谨慎行事,而不仅仅是捷径。【参考方案8】:
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。

【讨论】:

以上是关于运行时/已检查/未检查/错误/异常之间的差异的主要内容,如果未能解决你的问题,请参考以下文章

java遗珠之异常种类

java遗珠之异常种类

在JAVA中已检查异常和位未检查异常是啥?二者有何区别?

了解 Java 中的已检查与未检查异常

Java异常类复习总结

运行时检查失败 #2 - 变量“结果”周围的堆栈已损坏