第八课:异常处理
异常是程序运行过程中出现的错误情况,Java 提供强大的异常处理机制来应对这些情况,确保程序的稳定性和可用性。
- 异常 vs 错误:
- 错误(Error):无法恢复的严重问题,通常由 JVM 抛出。例如内存溢出 (
OutOfMemoryError)。 - 异常(Exception):程序可以处理的问题。
- 错误(Error):无法恢复的严重问题,通常由 JVM 抛出。例如内存溢出 (
(一)Java 中的异常分类
1. 检查性异常
- 用户引起的错误,编译时必须被处理。
- 例如:
IOException,SQLException。 - 特性:
- 必须通过
try-catch捕获或使用throws声明处理。
- 必须通过
- 示例:
try { BufferedReader reader = new BufferedReader(new FileReader("test.txt")); } catch (FileNotFoundException e) { e.printStackTrace(); }
2. 运行时异常
- 程序中的逻辑错误,编译时不强制处理。
- 属于
RuntimeException类的子类,例如:NullPointerException,ArrayIndexOutOfBoundsException。 - 特性:
- 运行时才出现。
- 开发中应尽量避免。
- 示例:
String str = null; System.out.println(str.length()); // 抛出 NullPointerException
3. 错误 (Error)
- JVM 抛出的严重问题,比如内存不足、栈溢出。
- 程序 通常无法恢复。如:
OutOfMemoryError,StackOverflowError。
(二)Java 异常处理的关键字
1. try-catch
- 包裹可能抛出异常的代码。
- 捕获并处理异常。
- 语法:
try { // 有可能抛出异常的代码 } catch (ExceptionType e) { // 异常的处理代码 } - 示例:
try { int result = 10 / 0; // 此处抛出 ArithmeticException } catch (ArithmeticException e) { System.out.println("错误:" + e.getMessage()); }
2. finally
-
用于清理资源,无论是否发生异常都会执行。
-
通常用于关闭文件、释放数据库连接等。
-
语法:
try { // 有可能抛出异常的代码 } catch (ExceptionType e) { // 异常的处理代码 } finally { // 始终会执行的代码 } -
示例:
try { int[] arr = new int[2]; System.out.println(arr[3]); // ArrayIndexOutOfBoundsException } catch (ArrayIndexOutOfBoundsException e) { System.out.println("数组越界异常:" + e.getMessage()); } finally { System.out.println("关闭资源"); }
3. throw
- 用于手动抛出一个异常。
- 通常用于验证条件不满足时抛出异常。
- 语法:
if (condition) { throw new ExceptionType("异常信息"); } - 示例:
public void checkAge(int age) { if (age < 18) { throw new IllegalArgumentException("年龄必须大于或等于 18"); } }
4. throws
- 用于声明方法可能抛出的异常,由调用者处理。
- 语法:
public void readFile() throws IOException { BufferedReader br = new BufferedReader(new FileReader("test.txt")); } - 示例:
public static void main(String[] args) throws IOException { readFile(); } public static void readFile() throws IOException { BufferedReader br = new BufferedReader(new FileReader("test.txt")); String line; while ((line = br.readLine()) != null) { System.out.println(line); } br.close(); }
(三)Java 内置异常类
Java 在 java.lang 包中定义了一些常见的异常类:
1. 运行时异常类
| 异常类型 | 描述 |
|---|---|
ArithmeticException | 数学运算异常,例如 除以零。 |
ArrayIndexOutOfBoundsException | 数组下标越界。 |
ClassCastException | 对象不能强制转换为子类。 |
IllegalArgumentException | 方法传递了非法参数。 |
NullPointerException | 试图访问 null 对象的成员或方法时抛出。 |
NumberFormatException | 试图将字符串解析为数字格式失败。 |
2. 检查性异常类
| 异常类型 | 描述 |
|---|---|
IOException | 输入/输出操作失败。 |
FileNotFoundException | 文件未找到。 |
SQLException | 数据库操作失败。 |
ClassNotFoundException | 当加载一个不存在的类时抛出。 |
InterruptedException | 线程中断时抛出。 |
(四)捕获多个异常
一个 try 块可以跟多个 catch 块;当发生异常时,会按顺序检查每个 catch 块。
语法:
try {
// 代码
} catch (ExceptionType1 e1) {
// 捕获异常类型1
} catch (ExceptionType2 e2) {
// 捕获异常类型2
}
示例:
try {
int[] arr = new int[2];
System.out.println(arr[3]); // 数组越界
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组越界异常");
} catch (NullPointerException e) {
System.out.println("空指针异常");
}
(五)自动关闭资源
JDK 7 后新增,用于自动关闭实现了 AutoCloseable 接口的资源(如文件流、数据库连接)。
优点:不需要显式关闭资源(如 close())。
语法:
try (资源声明) {
// 使用资源的代码
} catch (Exception e) {
// 异常捕获代码
}
示例:
import java.io.*;
public class TryWithResourcesExample {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("文件读取错误:" + e.getMessage());
}
}
}
(六)创建自定义异常
自定义异常类继承 Exception 或 RuntimeException 类。
步骤:
- 定义一个自定义异常类。
- 在需要的地方通过
throw抛出异常。
示例:
// 自定义异常类
class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message); // 调用父类构造器
}
}
// 使用自定义异常
public class CustomExceptionExample {
public void checkAge(int age) throws InvalidAgeException {
if (age < 18) {
throw new InvalidAgeException("年龄必须 >= 18");
}
}
public static void main(String[] args) {
CustomExceptionExample example = new CustomExceptionExample();
try {
example.checkAge(16); // 抛出异常
} catch (InvalidAgeException e) {
System.out.println("异常:" + e.getMessage());
}
}
}
输出:
异常:年龄必须 >= 18