throwable的唯二直接子类error与exception分别表示jvm严重故障和可干预异常;exception再分为编译强制处理的受检异常(如ioexception)和应靠测试暴露的运行时异常(如nullpointerexception)。

Java异常体系中,Throwable是所有可抛出对象的唯一根类,它不直接用于业务编码,而是通过两个明确分工的直接子类来划分问题性质:**Error** 和 **Exception**。这种划分不是随意的,而是围绕“谁该负责、能否恢复、是否该写代码处理”这三个实际工程问题设计的。
Throwable 下的两大核心分支:Error 与 Exception
Throwable 只有两个直接子类,这是整个体系的基石:
- Error:代表 JVM 层面的严重故障,比如 OutOfMemoryError、StackOverflowError、NoClassDefFoundError。这类问题程序本身无法修复,也不应捕获——捕获了也没法优雅恢复,强行 try-catch 反而掩盖真实缺陷。
- Exception:代表程序运行中可预期、可干预的异常情况,是开发者真正要关注和处理的部分。它进一步按编译期约束分为两类,而非按严重程度。
Exception 内部的实用二分法:受检异常 vs 运行时异常
Exception 的子类不是平铺罗列,而是有明确设计意图的分层:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 受检异常(Checked Exception):如 IOException、SQLException。编译器强制你显式处理(try-catch 或 throws),目的是提醒“这个操作依赖外部不稳定资源”,失败后通常不能自动重试成功,需要你决定降级、重试或向上透传。
- 运行时异常(RuntimeException):如 NullPointerException、IllegalArgumentException、ArrayIndexOutOfBoundsException。编译器不强制捕获,因为它们本质是**逻辑错误**,应靠代码审查、参数校验、单元测试提前暴露,而不是靠 catch 来兜底。
为什么不能直接继承 Throwable?
Throwable 本身缺少语义,既不表示“可恢复”也不表示“该忽略”。如果自定义异常直接继承它:
- 会绕过编译检查机制,让本该强制处理的外部依赖异常变成静默失败;
- 也会让本该在开发阶段就修复的空指针问题,被误当成需运行时捕获的正常流程;
- 主流框架(Spring、MyBatis)和日志系统都基于 Error/Exception 的语义做分类处理,违背这个约定会导致行为不可控。
业务异常该选哪条线?
自定义业务异常(如支付余额不足、库存超限)推荐继承 RuntimeException:
- 避免每个调用处都写 throws,污染方法签名;
- 符合“这是业务规则导致的失败,不是外部系统不可用”的定位;
- 便于统一用 AOP 或全局异常处理器(如 @ControllerAdvice)集中响应 HTTP 状态码和错误信息。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










