191. Java 异常 - 捕获与处理异常
在 Java 中,我们通过三大组件来编写异常处理逻辑:
✅
try
:用于包裹可能抛出异常的代码块 ✅catch
:用于捕获并处理异常 ✅finally
:无论是否发生异常,都会执行的代码块(如释放资源)
从 Java SE 7 开始,Java
又引入了一个更简洁的语法糖:
✅
try-with-resources
:特别适合处理如文件、网络流等需要关闭的资源(实现了Closeable
接口的类)
🎯 示例讲解:ListOfNumbers
类
我们来看一个例子,这个类的目标是:
- 创建一个包含
0~9
的整数列表 - 将这些数字写入一个文本文件
OutFile.txt
java
import java.io.*;
import java.util.List;
import java.util.ArrayList;
public class ListOfNumbers {
private List<Integer> list;
private static final int SIZE = 10;
public ListOfNumbers () {
list = new ArrayList<>(SIZE);
for (int i = 0; i < SIZE; i++) {
list.add(i); // 添加 0~9
}
}
public void writeList() {
// ❗ 这行会抛出 Checked Exception:IOException
PrintWriter out = new PrintWriter(new FileWriter("OutFile.txt"));
for (int i = 0; i < SIZE; i++) {
// ⚠️ 这行可能抛出 Unchecked Exception:IndexOutOfBoundsException
out.println("Value at: " + i + " = " + list.get(i));
}
out.close();
}
}
🔍 异常解释(两类异常的区别)
在这段代码中,有两种可能出错的地方:
1️⃣ new FileWriter("OutFile.txt")
- ❗ 受检异常(Checked Exception)
- 类型:
IOException
- 含义:可能文件不存在、没有写权限、磁盘满了等问题
- ✅ 必须显式
try-catch
或throws
2️⃣ list.get(i)
- ⚠️ 未受检异常(Unchecked Exception)
- 类型:
IndexOutOfBoundsException
- 含义:索引越界(比如
i = 10
时) - ⚠️ 可以不写 try-catch,编译器不强制要求
✅ 改进:添加异常处理
我们来修改 writeList()
方法,加入适当的异常处理逻辑:
java
public void writeList() {
PrintWriter out = null;
try {
out = new PrintWriter(new FileWriter("OutFile.txt")); // 可能抛 IOException
for (int i = 0; i <= SIZE; i++) { // ❗ 有意写错,触发越界
out.println("Value at: " + i + " = " + list.get(i));
}
} catch (IOException e) {
System.err.println("无法写入文件:" + e.getMessage());
} catch (IndexOutOfBoundsException e) {
System.err.println("访问数组越界:" + e.getMessage());
} finally {
if (out != null) {
out.close(); // 无论是否发生异常,最终关闭文件
}
}
}
✅ 推荐方式:使用 try-with-resources
java
public void writeList() {
try (PrintWriter out = new PrintWriter(new FileWriter("OutFile.txt"))) {
for (int i = 0; i < SIZE; i++) {
out.println("Value at: " + i + " = " + list.get(i));
}
} catch (IOException e) {
System.err.println("文件写入失败:" + e.getMessage());
}
}
✨ try-with-resources
的好处是:不需要手动关闭资源,系统会帮你自动调用 close()
,即使发生异常也不会忘关文件。
🎓小结:
异常来源 | 异常类型 | 编译器要求处理? | 推荐处理方式 |
---|---|---|---|
new FileWriter(...) |
IOException | ✅ 是 | try-catch 或 throws |
list.get(i) 超出范围 |
IndexOutOfBounds | ❌ 否 | 可以加 catch(防护) |
- "写文件就像租房子,可能租不到------那就得处理!"
- "数组越界就像走楼梯踩空了,未必每次都摔倒,但总有风险!"
- "try-with-resources 是自动洗碗机,用了就回不去了。"