本文通过文件读取、数组越界及自定义异常实例,揭示常见陷阱与最佳实践:避免吞没异常、优先具体捕获、慎用printStackTrace()。掌握异常处理能显著提升代码容错性与可维护性。
一、Java异常体系:三层防御网
Java异常继承自Throwable,分为三大类:
- Checked异常 (编译时异常)
继承Exception,非RuntimeException子类。编译器强制处理,代表可预测问题(如文件不存在)。
// 必须捕获或声明抛出
try {
Files.readString(Path.of("missing.txt"));
} catch (IOException e) { // 捕获IOException
System.err.println("文件读取失败: " + e.getMessage());
}
- Unchecked异常 (运行时异常)
继承RuntimeException。通常由代码逻辑错误引发(如空指针、数组越界),编译器不强制处理。
String str = null;
System.out.println(str.length()); // 抛出NullPointerException (未检查异常)
- 错误 (Error)
继承Error,标志严重系统故障(如内存耗尽OutOfMemoryError),程序通常无法恢复。
二、异常处理四剑客:try, catch, finally, throw
public class CustomException extends Exception { // 自定义Checked异常
public CustomException(String message) {
super(message);
}
}
public class ExceptionDemo {
public static void main(String[] args) {
try {
int[] arr = {1, 2};
System.out.println(arr[3]); // 抛出ArrayIndexOutOfBoundsException (运行时异常)
if (args.length == 0) {
throw new CustomException("缺少命令行参数"); // 主动抛出自定义异常
}
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("数组越界: " + e.getMessage());
} catch (CustomException e) {
System.out.println("自定义异常: " + e.getMessage());
} finally {
System.out.println("无论是否异常,finally块必执行!"); // 资源释放常在此进行
}
}
}
输出示例:
数组越界: Index 3 out of bounds for length 2
无论是否异常,finally块必执行!
三、关键陷阱与最佳实践
- 避免吞没异常:空catch块隐藏问题根源
- 精准捕获:优先捕获具体异常而非泛用Exception
- 资源管理:使用try-with-resources优于finally手动关闭
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
// 自动关闭资源
} catch (IOException e) { ... }
- 性能注意:异常构造开销大,勿用异常控制流程(如循环中频繁抛出捕获)
深度提示:throws用于方法声明可能抛出的异常(Checked异常必声明),throw用于在代码中主动引发异常对象。两者协作实现异常传播机制。
掌握Java异常处理,本质是构建代码的韧性——在错误发生时优雅降级、精准定位,而非放任崩溃。理解异常类型差异、熟练运用处理机制,方能写出真正可靠的工业级代码。
Java异常处理机制剖析与实践指南
1078

被折叠的 条评论
为什么被折叠?



