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

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

【问题讨论】:

标签: java exception exception-handling runtimeexception checked-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 引发,不应被捕获或处理)
        1. 虚拟机错误
        2. 断言错误
        3. 链接错误...等等
      • 运行时/取消检查异常(编程错误,不应被捕获或处理)
        1. NullPointerException
        2. ArrayIndexOutOfBoundException
        3. IllegalArgumentException ... 以此类推
      • 检查异常(其他任何情况,应捕获或处理应用程序)
        1. IOException
        2. FileNotFoundException
        3. 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。

            【讨论】:

              猜你喜欢
              • 2023-04-08
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多