Skip to content

⚠️ 异常处理

异常概述

异常(Exception)是程序运行过程中发生的错误或异常情况。Java 提供了完善的异常处理机制。

异常类型

  • Error:系统错误,程序无法处理
  • Exception:程序异常,可以处理
    • RuntimeException:运行时异常(非检查异常)
    • 其他 Exception:检查异常

异常类层次结构

Throwable
├── Error
│   ├── OutOfMemoryError
│   ├── StackOverflowError
│   └── ...
└── Exception
    ├── RuntimeException
    │   ├── NullPointerException
    │   ├── ArrayIndexOutOfBoundsException
    │   ├── IllegalArgumentException
    │   └── ...
    └── 其他 Exception
        ├── IOException
        ├── SQLException
        └── ...

try-catch-finally

基本语法

java
try {
    // 可能抛出异常的代码
} catch (ExceptionType e) {
    // 处理异常
} finally {
    // 无论是否发生异常都会执行的代码
}

示例

java
try {
    int result = 10 / 0;  // 抛出 ArithmeticException
} catch (ArithmeticException e) {
    System.out.println("除数不能为0: " + e.getMessage());
} finally {
    System.out.println("finally 块执行");
}

多个 catch

java
try {
    int[] arr = new int[5];
    arr[10] = 5;  // 可能抛出 ArrayIndexOutOfBoundsException
    int result = 10 / 0;  // 可能抛出 ArithmeticException
} catch (ArrayIndexOutOfBoundsException e) {
    System.out.println("数组索引越界: " + e.getMessage());
} catch (ArithmeticException e) {
    System.out.println("算术异常: " + e.getMessage());
} catch (Exception e) {
    System.out.println("其他异常: " + e.getMessage());
}

try-with-resources(Java 7+)

java
try (FileInputStream fis = new FileInputStream("file.txt")) {
    // 使用资源
    int data = fis.read();
} catch (IOException e) {
    System.out.println("IO 异常: " + e.getMessage());
}
// 资源自动关闭

throws 关键字

抛出异常

java
public void method() throws IOException {
    throw new IOException("IO 错误");
}

// 调用方法需要处理异常
try {
    method();
} catch (IOException e) {
    System.out.println("捕获异常: " + e.getMessage());
}

方法声明

java
public void readFile(String filename) throws IOException {
    FileInputStream fis = new FileInputStream(filename);
    // 读取文件
}

// 调用者必须处理异常
public void processFile() {
    try {
        readFile("file.txt");
    } catch (IOException e) {
        System.out.println("文件读取失败: " + e.getMessage());
    }
}

throw 关键字

抛出异常

java
public void validateAge(int age) {
    if (age < 0 || age > 150) {
        throw new IllegalArgumentException("年龄必须在 0-150 之间");
    }
}

// 使用
try {
    validateAge(-1);
} catch (IllegalArgumentException e) {
    System.out.println("验证失败: " + e.getMessage());
}

自定义异常

java
// 自定义异常类
public class CustomException extends Exception {
    public CustomException(String message) {
        super(message);
    }
}

// 使用
public void method() throws CustomException {
    throw new CustomException("自定义异常");
}

常见异常类型

RuntimeException(运行时异常)

java
// NullPointerException
String str = null;
int length = str.length();  // 抛出 NullPointerException

// ArrayIndexOutOfBoundsException
int[] arr = new int[5];
int value = arr[10];  // 抛出 ArrayIndexOutOfBoundsException

// IllegalArgumentException
public void setAge(int age) {
    if (age < 0) {
        throw new IllegalArgumentException("年龄不能为负数");
    }
}

// NumberFormatException
int num = Integer.parseInt("abc");  // 抛出 NumberFormatException

// ClassCastException
Object obj = "Hello";
Integer num = (Integer) obj;  // 抛出 ClassCastException

检查异常(Checked Exception)

java
// IOException
try {
    FileInputStream fis = new FileInputStream("file.txt");
} catch (IOException e) {
    System.out.println("IO 异常: " + e.getMessage());
}

// SQLException
try {
    Connection conn = DriverManager.getConnection(url);
} catch (SQLException e) {
    System.out.println("数据库异常: " + e.getMessage());
}

异常处理最佳实践

1. 捕获具体异常

java
// ✅ 好的做法:捕获具体异常
try {
    int result = 10 / 0;
} catch (ArithmeticException e) {
    System.out.println("算术异常: " + e.getMessage());
}

// ❌ 不好的做法:捕获所有异常
try {
    int result = 10 / 0;
} catch (Exception e) {
    System.out.println("异常: " + e.getMessage());
}

2. 不要忽略异常

java
// ❌ 不好的做法:忽略异常
try {
    processFile();
} catch (IOException e) {
    // 什么都不做
}

// ✅ 好的做法:至少记录日志
try {
    processFile();
} catch (IOException e) {
    System.err.println("处理文件失败: " + e.getMessage());
    e.printStackTrace();
}

3. 使用 finally 清理资源

java
// ✅ 好的做法:使用 finally 清理资源
FileInputStream fis = null;
try {
    fis = new FileInputStream("file.txt");
    // 使用资源
} catch (IOException e) {
    System.out.println("IO 异常: " + e.getMessage());
} finally {
    if (fis != null) {
        try {
            fis.close();
        } catch (IOException e) {
            System.out.println("关闭文件失败: " + e.getMessage());
        }
    }
}

4. 使用 try-with-resources

java
// ✅ 更好的做法:使用 try-with-resources
try (FileInputStream fis = new FileInputStream("file.txt")) {
    // 使用资源
} catch (IOException e) {
    System.out.println("IO 异常: " + e.getMessage());
}
// 资源自动关闭

完整示例

java
public class ExceptionExample {
    // 方法抛出异常
    public static void divide(int a, int b) throws ArithmeticException {
        if (b == 0) {
            throw new ArithmeticException("除数不能为0");
        }
        int result = a / b;
        System.out.println("结果: " + result);
    }
    
    // 读取文件
    public static void readFile(String filename) throws IOException {
        FileInputStream fis = new FileInputStream(filename);
        int data;
        while ((data = fis.read()) != -1) {
            System.out.print((char) data);
        }
        fis.close();
    }
    
    // 验证年龄
    public static void validateAge(int age) {
        if (age < 0 || age > 150) {
            throw new IllegalArgumentException("年龄必须在 0-150 之间");
        }
        System.out.println("年龄有效: " + age);
    }
    
    public static void main(String[] args) {
        // 处理算术异常
        try {
            divide(10, 0);
        } catch (ArithmeticException e) {
            System.out.println("捕获异常: " + e.getMessage());
        }
        
        // 处理 IO 异常
        try {
            readFile("file.txt");
        } catch (IOException e) {
            System.out.println("文件读取失败: " + e.getMessage());
        }
        
        // 处理参数异常
        try {
            validateAge(-1);
        } catch (IllegalArgumentException e) {
            System.out.println("验证失败: " + e.getMessage());
        }
        
        // 使用 try-with-resources
        try (FileInputStream fis = new FileInputStream("file.txt")) {
            int data = fis.read();
            System.out.println("读取数据: " + data);
        } catch (IOException e) {
            System.out.println("IO 异常: " + e.getMessage());
        }
    }
}

下一步

掌握了异常处理后,可以继续学习:


💡 提示:良好的异常处理可以提高程序的健壮性,正确处理异常是编写高质量代码的重要部分