JAVA学习之异常

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.异常处理关键字

  1. try: 包裹可能抛出异常的代码块
  2. catch: 捕获并处理特定类型的异常(可多个,子类在前父类在后)
  3. finally: 无论是否异常都会执行,常用于资源释放
  4. throw: 手动抛出一个异常对象
  5. 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
  1. 精确捕获:只捕获你能处理的异常,不要笼统地 catch (Exception e)
  2. 保留异常链:重新包装异常时传入原始异常 new ServiceException("msg", cause)
  3. 使用日志框架记录异常:log.error("描述", e) 而非 e.printStackTrace()
  4. 自定义业务异常:继承 RuntimeException,携带错误码和业务信息

避免

  1. 吞掉异常:catch 块为空或仅打印消息而不处理/传播
  2. 用异常控制业务流程:异常有性能开销,不应用于正常逻辑分支
  3. 在 finally 中 return:会覆盖 try/catch 中的返回值和异常
  4. 过度使用 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.面试高频点速记

  1. NoClassDefFoundError vs ClassNotFoundException:前者是运行时找不到类(Error),后者是动态加载时找不到(Checked Exception)
  2. final / finally / finalize 的区别
  3. try-with-resources 的原理:AutoCloseable 接口 + 编译器生成关闭代码
  4. 异常对性能的影响:创建异常对象时需要填充栈快照(fillInStackTrace),这是主要开销
相关推荐
m0_639906942 小时前
HashMap:哈希扰动、扩容源码、红黑树转换、并发问题
java·算法·哈希算法
神魔皆以血嗜2 小时前
Java 存储金额
java·后端
SL_staff3 小时前
周报越厚问题越拖?用结构化执行机制让周报回归决策价值
java·spring cloud·开源
梅梅绵绵冰3 小时前
JVM虚拟机
java·开发语言·jvm
golang学习记3 小时前
Python vs Go:2026年到底该怎么选
java·vscode·python·golang·pycharm·goland
Shaoshing4 小时前
消息顺序
java·开发语言
我命由我123454 小时前
SQL 检测脚本
java·数据库·sql·功能测试·单元测试·压力测试·可用性测试
Hpc_Fun4 小时前
GPU 工作站品牌怎么比?五把可核验尺子、加权评分脚本与场景重排
java·信创·gpu工作站·品牌对比·加权评分
const_qiu4 小时前
第四章 03:4.3 Tools —— 让 Agent 会用工具
java·人工智能