Java 中的内置异常

2025年5月20日 | 阅读 7 分钟

Java 库中已经存在的 异常 被称为 内置异常。这些异常能够定义错误情况,以便我们能够理解出现此错误的原因。

内置异常的类型

内置异常有两种类型:

  • 已检查异常
  • 未检查异常
Built-in Exceptions in Java

已检查异常

已检查 异常被称为 编译时 异常,因为这些异常在编译时由编译器检查。编译器会确保程序员是否处理了异常。程序员必须处理该异常;否则,系统将显示编译错误。

已检查异常列表

  1. ClassNotFoundException: 在运行时找不到类时抛出。
  2. InterruptedException: 当线程在等待或睡眠时被中断时发生。
  3. IOException: 它表示 I/O 操作失败,例如读取缺失的文件。
  4. NoSuchMethodException: 当类中不存在请求的方法时引发。
  5. CloneNotSupportedException: 当对象不支持克隆时抛出。
  6. FileNotFoundException: 尝试打开不存在的文件失败时发生。
  7. IllegalAccessException: 当访问类或方法被拒绝时引发。
  8. InstantiationException: 尝试实例化抽象类失败时抛出。
  9. NoSuchFieldException: 当类中不存在请求的字段时发生。
  10. SQLException: 表示与数据库访问和 SQL 操作相关的错误。

已检查异常示例

示例

输出

Main.java:5: error: unreported exception FileNotFoundException; must be caught or declared to be thrown
        file_data = new FileInputStream("C:/Users/Desktop/Hello.txt");  
                    ^
Main.java:7: error: unreported exception IOException; must be caught or declared to be thrown
        while(( m = file_data.read() ) != -1) {  
                                  ^
Main.java:10: error: unreported exception IOException; must be caught or declared to be thrown
        file_data.close();  
                       ^
3 errors

在上面的代码中,我们尝试读取 Hello.txt 文件以在控制台上显示其数据。运行上述程序时,我们会收到以下异常:

  1. FileInputStream(File filename) 构造函数抛出 FileNotFoundException,这是一个已检查异常。
  2. FileInputStream 类的 read() 方法抛出 IOException
  3. close() 方法也抛出 IOException。

处理已检查异常

基本上有两种方法可以处理这些异常。

  • 使用 throws 关键字
  • 使用 try-catch 块

使用 throws 关键字

异常发生在 main() 方法中。我们可以通过使用 throws 关键字在 main() 方法中声明异常来消除这些编译错误。我们只声明 IOException,而不声明 FileNotFoundException,因为存在父子关系。IOException 类是 FileNotFoundException 类的父类,因此 IOException 会自动处理此异常。我们将按以下方式声明异常:

示例

当我们通过使用 throws 关键字处理 IOException 并编译运行上述代码时,我们会得到以下输出:

Hello Java

使用 try-catch 块

我们也可以使用 try-catch 来处理此异常。但是,我们上面使用的方式不正确。我们必须为每个异常提供有意义的消息,这样更容易理解错误。我们将按以下方式使用 try-catch 块:

示例

输出

File Not Found!
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.io.FileInputStream.read()" because "<local1>" is null
	at Main.main(Main.java:12)

我们将在控制台上看到正确的错误消息 “文件未找到!”,因为该位置没有 Hello.txt 文件。我们在控制台上收到以下消息:

未检查异常

未检查 异常恰好与 已检查 异常相反。它也称为运行时异常。编译器不会在编译时检查这些异常。简单来说,如果程序抛出未检查异常,即使我们没有处理或声明它,程序也不会给出编译错误。通常,当用户在与程序交互时提供错误数据时,就会发生这种情况。

注意:由于父子关系,RuntimeException 类能够解决所有未检查的异常。

未检查异常列表

  1. ArithmeticException: 当发生异常的算术条件时抛出,例如除以零。
  2. ArrayIndexOutOfBoundsException: 尝试使用非法索引访问数组元素时抛出。
  3. ArrayStoreException: 尝试将错误类型的元素存储到数组中时抛出。
  4. NullPointerException: 尝试使用 null 引用时抛出。
  5. IllegalStateException: 在非法或不适当的时间调用方法时抛出。
  6. ClassCastException: 尝试将对象强制转换为非该对象实例的类时抛出。
  7. IllegalThreadStateException: 在非法或不适当的时间调用方法时抛出。
  8. IllegalArgumentException: 当方法接收的参数格式与预期不同时抛出。
  9. NumberFormatException: 尝试将字符串转换为数字类型,但字符串格式不正确时抛出。
  10. UnsupportedOperationException: 当操作不受支持时抛出。

未检查异常示例

ArithmeticException:除以零

示例

输出

Runtime Error:
Exception in thread "main" java.lang.ArithmeticException: / by zero
	at Main.main(Main.java:7)

在上面的程序中,我们将 35 除以 0。代码会成功编译,但会在运行时抛出 ArithmeticException 错误。将数字除以 0 会抛出除零异常,这是一个未检查异常。

让我们看另一个未检查异常的例子。

ArrayIndexOutOfBoundsException 示例

示例

输出

Runtime Error:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 7 out of bounds for length 6
	at Main.main(Main.java:6)

在上面的代码中,我们试图获取位于位置 7 的元素,但数组的长度是 6。代码编译成功,但在运行时抛出 ArrayIndexOutOfBoundsException。

处理未检查异常

Java 中的未检查异常是运行时异常,不需要在方法签名中捕获或声明。它们通常表示编程错误,例如 NullPointerException、ArrayIndexOutOfBoundsException 或 IllegalArgumentException。

  • 验证输入:通过在使用输入之前进行检查,可以防止 IllegalArgumentException 等异常。
  • 使用 Try-Catch 块:处理未检查异常可能发生的特定情况。
  • 执行防御性编程:始终检查 null 引用或确保数组访问安全。
  • 日志记录和调试:始终记录异常以便有效分析问题。

已检查异常与未检查异常的区别

方面已检查异常未检查异常
编译时行为这些异常在编译时进行检查。这些异常也在编译时处理。这些异常恰好与已检查异常相反。这些异常在编译时未被检查和处理。
层级结构这些异常是异常的直接子类,但不是从 RuntimeException 类扩展的。它们是 RuntimeException 类的直接子类。
编译器强制执行如果方法抛出已检查异常,代码将产生编译错误。编译器无法自行处理异常。代码编译时不会出错,因为这些异常会逃过编译器的注意。这些异常是用户在编程逻辑中创建的错误的后果。
发生情况这些异常主要发生在失败的可能性很高的情况下。这些异常主要由于编程错误而发生。
示例常见的已检查异常包括 IOException、DataAccessException、InterruptedException 等。常见的未检查异常包括 ArithmeticException、InvalidClassException、NullPointerException 等。
传播这些异常使用 throws 关键字进行传播。它们会自动传播。
处理要求需要提供 try-catch 和 try-finally 块来处理已检查异常。对于未检查异常,这不是强制性的。

我们不希望并且会限制程序正常执行的 Bug 或错误被称为 异常

Java 已检查和未检查异常 MCQs

1. 下列哪项是已检查异常?

  1. IOException
  2. NumberFormatException
  3. NullPointerException
  4. IllegalArgumentException
 

答案:1)

解释:IOException 是已检查异常,其他三个是未检查异常。


2. 下列哪项是未检查异常?

  1. NoSuchMethodException
  2. NumberFormatException
  3. NoSuchFieldException
  4. ClassNotFoundException
 

答案:2)

解释:NumberFormatException 是未检查异常,其他三个是已检查异常。


3. 下列哪个异常不需要在方法签名中捕获或声明?

  1. NoSuchFieldException
  2. ClassNotFoundException
  3. ArrayIndexOutOfBoundsException
  4. NoSuchMethodException
 

答案:3)

解释:Java 中的未检查异常是运行时异常,不需要在方法签名中捕获或声明。它们通常表示编程错误,例如 NullPointerException、ArrayIndexOutOfBoundsException 或 IllegalArgumentException。


4. 如何处理已检查异常?

  1. 使用 throws 关键字
  2. 使用 try-catch 块
  3. 使用 throw 关键字
  4. 仅 1 和 2
 

答案:4)

解释:基本上有两种方法可以处理已检查异常:使用 throws 关键字和 try-catch 块。


5. 下列哪个类是所有异常和错误的父类?

  1. Throwable
  2. Exception
  3. Error
  4. Object
 

答案:1)

解释:在 Java 中,Throwable 是所有异常和错误的父类。它有两个直接子类:

Exception:表示应用程序中可恢复的条件。已检查异常继承此类。

Error:表示严重的 JVM 相关问题,例如 OutOfMemoryError。