Skip to content

Java 异常处理

异常 (Exception) 是在程序执行期间发生的、中断程序正常指令流的事件。Java 提供了一个强大的异常处理框架,允许开发者优雅地捕获和处理这些错误,从而创建更健壮、更可靠的应用程序。

什么是异常?

在 Java 中,异常是一个对象,它封装了关于错误的详细信息,例如错误的类型和程序出错时的状态。当错误发生时,系统会创建一个异常对象并将其“抛出”(throw)。

异常的分类

所有异常对象都是 java.lang.Throwable 类的子类。Throwable 有两个主要的子类:ErrorException

  • Error: 表示严重的问题,通常是应用程序无法处理的,例如 OutOfMemoryError(内存溢出)或 StackOverflowError(栈溢出)。程序通常不应该尝试捕获 Error

  • Exception: 表示应用程序可以处理的异常情况。它又分为两类:

    1. 受检异常 (Checked Exceptions): 这类异常在编译时就必须被处理,否则代码无法通过编译。通常是程序外部的、不可预见的错误,如 IOException(文件未找到)。开发者必须使用 try-catch 捕获或使用 throws 声明抛出。
    2. 非受检异常 (Unchecked Exceptions / Runtime Exceptions): 这类异常在编译时不被检查,通常是由程序逻辑错误引起的,例如 NullPointerException(空指针引用)、ArrayIndexOutOfBoundsException(数组越界)或 ArithmeticException(算术错误,如除以零)。虽然可以捕获它们,但更好的做法是修复代码逻辑来避免它们。

try-catch 语句

这是处理异常的核心机制。将可能抛出异常的代码放在 try 块中,并使用 catch 块来捕获和处理特定类型的异常。

java
public class TryCatchExample {
    public static void main(String[] args) {
        try {
            // 可能会导致异常的代码
            int[] numbers = {1, 2, 3};
            System.out.println(numbers[5]); // 数组越界
        } catch (ArrayIndexOutOfBoundsException e) {
            // 捕获并处理异常
            System.out.println("发生错误:数组索引超出范围!");
            // 打印异常的堆栈跟踪信息,便于调试
            e.printStackTrace();
        }
        System.out.println("程序继续执行...");
    }
}

一个 try 块后面可以跟多个 catch 块,以处理不同类型的异常。

finally 关键字

finally 块中的代码无论是否发生异常,都保证会被执行(除非 JVM 退出)。它通常用于释放资源,如关闭文件流或数据库连接。

java
import java.io.*;

public class FinallyExample {
    public static void main(String[] args) {
        PrintWriter writer = null;
        try {
            writer = new PrintWriter(new FileWriter("output.txt"));
            writer.println("Hello, World!");
        } catch (IOException e) {
            System.err.println("文件写入失败: " + e.getMessage());
        } finally {
            // 确保 writer 总是被关闭
            if (writer != null) {
                writer.close();
                System.out.println("PrintWriter 已关闭。");
            }
        }
    }
}

throwthrows 关键字

  • throw: 用于在代码中主动抛出一个异常对象。通常用于报告自定义的错误条件。

    java
    public void checkAge(int age) {
        if (age < 18) {
            throw new IllegalArgumentException("年龄必须大于或等于 18 岁");
        }
        System.out.println("年龄合法。");
    }
  • throws: 用在方法签名中,声明该方法可能会抛出一种或多种类型的受检异常。它告诉方法的调用者,调用此方法时必须处理这些声明的异常。

    java
    import java.io.IOException;
    
    // 声明此方法可能抛出 IOException
    public void readFile(String filePath) throws IOException {
        // ... 读取文件的代码 ...
    }
    
    // 调用者必须处理这个异常
    public void processFile() {
        try {
            readFile("myFile.txt");
        } catch (IOException e) {
            System.err.println("处理文件时出错。");
        }
    }

try-with-resources 语句 (Java 7+)

对于实现了 java.lang.AutoCloseable 接口的资源(如文件流、数据库连接),try-with-resources 语句可以极大地简化资源管理。它能确保在 try 块执行完毕后,资源被自动关闭,无需手写 finally 块。

java
import java.io.*;

public class TryWithResourcesExample {
    public static void main(String[] args) {
        // writer 会在 try 块结束时自动关闭
        try (PrintWriter writer = new PrintWriter(new FileWriter("log.txt"))) {
            writer.println("这是一个自动管理的日志条目。");
        } catch (IOException e) {
            System.err.println("日志写入失败: " + e.getMessage());
        }
    }
}

这是现代 Java 中处理资源的推荐方式。

本站内容仅供学习和研究使用。