Java 异常处理2025 年 4 月 25 日 | 阅读 12 分钟 Java 中的异常处理是一种强大的机制,用于处理运行时错误,从而可以维持应用程序的正常流程。 在本节中,我们将学习 Java 异常、其类型以及已检查异常和未检查异常之间的区别。 Java 中的异常是什么?在 Java 中,异常是在程序执行期间发生的事件,它会中断指令的正常流程。这些异常可能由于各种原因发生,例如无效的用户输入、找不到文件或除以零。当发生异常时,通常由 `java.lang.Exception` 类的一个子类对象表示。 什么是异常处理?异常处理是一种处理运行时错误(如 `ClassNotFoundException`、`IOException`、`SQLException`、`RemoteException` 等)的机制。 异常处理的优势异常处理的核心优势在于维持应用程序的正常流程。异常通常会中断应用程序的正常流程;这就是为什么我们需要处理异常。让我们考虑一个场景 假设一个 Java 程序有 10 条语句,并且在第 5 条语句处发生了一个异常;其余代码将不会执行,即第 6 到 10 条语句将不会执行。但是,当我们执行异常处理时,其余的语句将执行。这就是为什么我们在 Java 中使用异常处理。 Java 异常类层次结构`java.lang.Throwable` 类是 Java 异常层次结构中由 `Exception` 和 `Error` 两个子类继承的根类。Java 异常类的层次结构如下所示 ![]() Java 异常的类型在 Java 中,异常分为两种主要类型:已检查异常和未检查异常。此外,还有第三种称为错误的类别。让我们深入了解这些类型
![]() 1. 已检查异常已检查异常是在编译时检查的异常。这意味着编译器会验证代码是否通过捕获它们或使用 `throws` 关键字在方法签名中声明它们来处理这些异常。已检查异常的示例包括 IOException: 当输入/输出操作失败时,例如从文件读取或写入文件时,会抛出异常。 SQLException: 访问数据库时发生错误时会抛出此异常。 ParseException: 表示在将字符串解析为其他数据类型(例如解析日期)时出现问题。 ClassNotFoundException: 当应用程序尝试通过其字符串名称(使用 `Class.forName()` 等方法)加载类时,但找不到具有指定名称的类(在类路径中)时,会抛出此异常。 2. 未检查异常 (运行时异常)未检查异常,也称为运行时异常,在编译时不会进行检查。这些异常通常是由于编程错误引起的,例如代码中的逻辑错误或不正确的假设。它们不需要在方法签名中使用 `throws` 关键字声明,因此处理它们是可选的。未检查异常的示例包括 NullPointerException: 当尝试在为 null 的对象引用上访问或调用方法时,会抛出此异常。 ArrayIndexOutOfBoundsException: 当我们尝试使用无效索引访问数组元素时,会发生此异常。 ArithmeticException: 算术运算失败时(例如除以零)会抛出此异常。 IllegalArgumentException: 表示方法收到了非法或不恰当的参数。 3. 错误错误表示在正常情况下不应捕获的异常情况。它们通常是由应用程序无法控制的问题引起的,例如系统故障或资源耗尽。应用程序代码不应捕获或处理错误。错误的示例包括 OutOfMemoryError: 当 Java 虚拟机 (JVM) 无法为应用程序分配足够的内存时,会发生此错误。 StackOverflowError: 由于过度递归导致栈内存耗尽时,会抛出此错误。 NoClassDefFoundError: 表示 JVM 找不到在编译时可用的类的定义。 理解 Java 中不同类型的异常对于编写健壮可靠的代码至关重要。通过适当地处理异常,可以提高应用程序的弹性并提供更好的用户体验。异常处理层次结构 Java 异常关键字Java 提供了五个用于处理异常的关键字。下表描述了每个关键字。
Java 异常处理示例让我们来看一个 Java 异常处理的示例,其中我们使用 try-catch 语句来处理异常。 示例编译并运行输出 Exception in thread main java.lang.ArithmeticException:/ by zero rest of the code... 在上面的示例中,100/0 会引发一个 `ArithmeticException`,它由 try-catch 块处理。 try-catch 块Java 中处理异常的主要机制之一是 try-catch 块。try 块包含可能抛出异常的代码,catch 块用于在异常发生时处理该异常。这是一个基本示例 处理多个异常您可以通过提供多个 catch 块来处理多种类型的异常,每个块捕获不同类型的异常。这允许您根据抛出的具体异常类型来定制异常处理逻辑。这是一个示例 finally 块除了 try 和 catch 之外,Java 还提供了 finally 块,它允许您执行清理代码(例如关闭资源),无论是否发生异常。finally 块通常用于释放在 try 块中获取的资源。这是一个示例 Java 异常的常见场景以下是一些可能发生未检查异常的场景。它们如下 1) 发生 ArithmeticException 的场景如果我们用零除任何数字,就会发生 `ArithmeticException`。 这是一个简单的 Java 代码示例,其中发生 `ArithmeticException` 示例编译并运行输出 Error: Division by zero is not allowed. 说明 我们有一个 `main()` 方法,其中我们尝试执行除以零的操作,这在算术中是不允许的。 在 try 块内部,我们执行除法运算 `dividend / divisor`,其中 `divisor` 的值为 0。 当发生除以零的情况时,会抛出 `ArithmeticException`。我们使用专门用于 `ArithmeticException` 的 catch 块来捕获此异常。 在 catch 块中,我们通过打印错误消息来处理异常,表明不允许除以零。如果需要,可以在此处添加其他错误处理逻辑。 2) 发生 NullPointerException 的场景如果任何变量的值为 null,则对该变量执行任何操作都会抛出 `NullPointerException`。 这是一个 Java 代码示例,其中发生 `NullPointerException` 示例编译并运行输出 Error: Null reference encountered. 说明 我们有一个 `main()` 方法,其中我们将 String 变量 `str` 初始化为 null。 在 try 块内部,我们尝试在 `str` 引用上调用 `length()` 方法,该引用为 null。 当尝试在 null 引用上调用方法时,会抛出 `NullPointerException`。 我们使用专门用于 `NullPointerException` 的 catch 块来捕获此异常。 在 catch 块中,我们通过打印错误消息来处理异常,表明遇到了 null 引用。如果需要,可以在此处添加其他错误处理逻辑。 3) 发生 NumberFormatException 的场景如果任何变量或数字的格式不匹配,可能会导致 `NumberFormatException`。假设我们有一个包含字符的字符串变量;将此变量转换为数字将导致 `NumberFormatException`。 这是一个 Java 代码示例,其中发生 `NumberFormatException` 示例编译并运行输出 Error: Unable to parse the string as an integer. 说明 我们有一个 `main()` 方法,其中我们将 String 变量 `str` 初始化为非数字字符。 在 try 块内部,我们尝试使用 `Integer.parseInt()` 方法将字符串 `str` 解析为整数。 由于字符串包含非数字字符,因此解析操作会抛出 `NumberFormatException`。 我们使用专门用于 `NumberFormatException` 的 catch 块来捕获此异常。 在 catch 块中,我们通过打印错误消息来处理异常,表明该字符串无法解析为整数。如果需要,可以在此处添加其他错误处理逻辑。 4) 发生 ArrayIndexOutOfBoundsException 的场景当数组超出其大小时,会发生 `ArrayIndexOutOfBoundsException`。可能还有其他原因导致 `ArrayIndexOutOfBoundsException`。考虑以下语句。 这是一个 Java 代码示例,其中发生 `ArrayIndexOutOfBoundsException` 示例编译并运行输出 Error: Index is out of bounds. 说明 我们有一个 `main()` 方法,其中我们将数组 `numbers` 初始化为 5 个元素。 在 try 块内部,我们尝试访问索引 10 处的元素,该索引超出了数组 `numbers` 的范围。 由于索引超出了范围,因此会抛出 `ArrayIndexOutOfBoundsException`。 我们使用专门用于 `ArrayIndexOutOfBoundsException` 的 catch 块来捕获此异常。 在 catch 块中,我们通过打印错误消息来处理异常,表明索引超出了范围。如果需要,可以在此处添加其他错误处理逻辑。 异常处理最佳实践捕获特定异常: 尽可能捕获特定异常,而不是捕获通用的 `Exception` 对象。这有助于提供更精确的错误处理,并使代码更易于理解和维护。 保持异常处理简单: 避免过于复杂的异常处理逻辑。保持 catch 块简洁,并专注于处理它们设计的特定异常。复杂的异常处理逻辑可能会使代码难以调试和维护。 记录异常: 处理异常时,请务必记录异常或错误消息。这有助于在生产环境中进行故障排除和诊断问题。 适当地抛出异常: 在必要时抛出异常,但要避免过度使用已检查异常。已检查异常应用于调用者可以合理预期处理的异常情况。 使用自定义异常: 为应用程序中的特定错误情况创建自定义异常类。这有助于提供有意义的错误消息,并使代码更具自我文档化。 结论异常处理是 Java 编程的一个基本方面。通过遵循最佳实践和采用有效的异常处理策略,您可以编写更健壮、可维护的 Java 应用程序。请记住捕获特定异常、保持异常处理简单、记录异常以进行调试、适当地抛出异常以及在需要时使用自定义异常。掌握异常处理将帮助您构建更可靠的软件,该软件能够优雅地处理错误和异常。 Java 异常处理选择题1. 如果一个方法抛出了一个它没有声明的已检查异常,会发生什么?
答案:a) 解释:如果一个方法抛出了一个它没有声明的已检查异常,会导致编译错误。 2. 关于 finally 块,以下哪项是正确的?
答案:a) 解释:无论是否抛出异常,finally 块总是在 try 块之后执行。 3. NullPointerException 是什么类型的异常?
答案:b) 解释:NullPointerException 是一个未检查异常,意味着它不需要被声明或捕获。 4. 关于自定义异常,以下哪项陈述是正确的?
答案:c) 解释:自定义异常必须继承自 Exception 类或其子类之一。 5. Java 中的异常传播是什么?
答案:c) 解释:将异常从一个方法传递到其调用方法的进程 |
我们请求您订阅我们的新闻通讯以获取最新更新。