JAVA异常
Java 异常(Exception)是 Java 语言中用于处理程序运行时错误和非正常流程的核心机制。它允许程序在遇到问题时优雅地处理,而不是直接崩溃
1.异常体系结构
Java 的所有异常都继承自 java.lang.Throwable 类,主要分为两大分支
scss
Throwable
├── Error (严重错误)
│ ├── OutOfMemoryError (内存溢出)
│ ├── StackOverflowError (栈溢出)
│ └── NoClassDefFoundError (类定义缺失)
│
└── Exception (可处理的异常)
├── Checked Exception (受检异常/编译时异常)
│ ├── IOException
│ ├── SQLException
│ └── ClassNotFoundException
│
└── RuntimeException (非受检异常/运行时异常)
├── NullPointerException (空指针)
├── ArrayIndexOutOfBoundsException (数组越界)
├── ClassCastException (类型转换错误)
├── IllegalArgumentException (非法参数)
└── ArithmeticException (算术异常,如除零)
2.三大核心分类
| 分类 | 说明 | 编译器检查 | 典型示例 | 处理建议 |
|---|---|---|---|---|
| Error | JVM 层面的严重问题,程序无法恢复 | ❌ 不检查 | OOM、StackOverflow | 不应捕获,应修复代码或调整JVM参数 |
| Checked Exception | 外部因素导致的可预见异常 | ✅ 必须处理 | IO、网络、数据库 | 用 try-catch 或 throws 声明 |
| RuntimeException | 编程逻辑错误导致的异常 | ❌ 不检查 | 空指针、越界 | 通过代码规范避免,而非依赖捕获 |
3.异常处理关键字
- try: 包裹可能抛出异常的代码块
- catch: 捕获并处理特定类型的异常(可多个,子类在前父类在后)
- finally: 无论是否异常都会执行,常用于资源释放
- throw: 手动抛出一个异常对象
- throws: 在方法签名上声明该方法可能抛出的异常
java
// 标准用法示例
public String readFile(String path) throws IOException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader(path));
return reader.readLine();
} catch (FileNotFoundException e) {
System.err.println("文件不存在: " + path);
throw e; // 重新抛出
} catch (IOException e) {
System.err.println("读取失败: " + e.getMessage());
return null;
} finally {
// 传统方式关闭资源
if (reader != null) {
try { reader.close(); } catch (IOException ignored) {}
}
}
}
4.现代最佳实践
使用 try-with-resources(Java 7+)自动管理资源
java
try (BufferedReader reader = new BufferedReader(new FileReader(path))) {
return reader.readLine();
} // 自动关闭,无需 finally
- 精确捕获:只捕获你能处理的异常,不要笼统地 catch (Exception e)
- 保留异常链:重新包装异常时传入原始异常 new ServiceException("msg", cause)
- 使用日志框架记录异常:log.error("描述", e) 而非 e.printStackTrace()
- 自定义业务异常:继承 RuntimeException,携带错误码和业务信息
避免
- 吞掉异常:catch 块为空或仅打印消息而不处理/传播
- 用异常控制业务流程:异常有性能开销,不应用于正常逻辑分支
- 在 finally 中 return:会覆盖 try/catch 中的返回值和异常
- 过度使用 Checked Exception:现代框架(Spring等)普遍倾向 RuntimeException
5.自定义异常示例
java
public class BusinessException extends RuntimeException {
private final int code;
public BusinessException(int code, String message) {
super(message);
this.code = code;
}
public BusinessException(int code, String message, Throwable cause) {
super(message, cause); // 保留异常链
this.code = code;
}
public int getCode() { return code; }
}
// 使用
if (user == null) {
throw new BusinessException(404, "用户不存在");
}
6.面试高频点速记
- NoClassDefFoundError vs ClassNotFoundException:前者是运行时找不到类(Error),后者是动态加载时找不到(Checked Exception)
- final / finally / finalize 的区别
- try-with-resources 的原理:AutoCloseable 接口 + 编译器生成关闭代码
- 异常对性能的影响:创建异常对象时需要填充栈快照(fillInStackTrace),这是主要开销