runtimeexception 反映程序逻辑稳定性缺陷,需通过预防而非捕获来提升健壮性;空指针、越界、类型转换及参数非法等异常源于校验缺失;应采用防御性编程、输入约束、optional 等手段主动规避,并通过完整日志与异常链定位问题。

RuntimeException 直接反映程序在运行时的逻辑稳定性。它不强制捕获,但一旦发生,往往意味着代码存在未覆盖的边界条件或校验缺失——这不是“意外”,而是设计疏漏。提升健壮性,关键不是靠 catch 住所有 RuntimeException,而是让它们尽可能不发生。
空指针与数组越界:最常暴露的健壮性缺口
NullPointerException 和 ArrayIndexOutOfBoundsException 占运行时异常的多数。它们不是随机出现的,而是源于对输入、状态或数据结构的盲目信任。
- 对象使用前不判 null,比如直接调用
user.getName()而没确认user != null - 遍历集合用传统 for 循环却硬写
i ,或把 <code>list.get(0)当成安全操作 - 从外部(如 HTTP 请求、配置文件)读取的数据未做非空、长度、范围校验就直接参与计算或索引
类型转换与参数非法:语义校验的失守
ClassCastException 和 IllegalArgumentException 表明程序在“相信”类型或参数合法性上过于乐观。
- 用
(User) obj强转前没加obj instanceof User判断 - 方法接收 int 类型的 pageSize,却允许传入 -1 或 1000000,后续导致数据库查询失败或内存溢出
- 将用户提交的字符串直接传给
Integer.parseInt(),没包裹 try-catch 或提前用正则过滤数字格式
防御性编程比异常捕获更有效
对 RuntimeException,优先策略是预防,而非兜底。catch 它们容易掩盖问题本质,还可能遗漏资源清理。
- 接口入参用
Objects.requireNonNull()或自定义校验工具快速失败 - 集合操作优先用增强 for 或 Stream API,避免手动索引;必要时用
Math.min(i, list.size() - 1)做兜底 - 对外部输入做最小化约束:长度、正则、枚举值匹配,并在业务层统一拦截非法请求
- 把空值、默认值、可选类型(Optional)作为设计习惯,而不是异常后的补救手段
日志与异常链:让失败成为改进依据
即使 RuntimeException 发生了,也要让它“说得清楚”。静默吞掉或只打 e.getMessage() 会让健壮性退化为黑盒。
- 记录日志时保留原始异常对象:
log.error("Failed to process order {}", orderId, e) - 封装异常时传入 cause:
throw new BusinessException("库存扣减失败", e) - 敏感字段脱敏,但保留上下文变量(如用户 ID、订单号、操作时间),便于定位故障场景










