空指针异常是程序逻辑错误,需按场景区分处理:支付模块应转为业务异常并warn日志,工具类须fail-fast;外部调用要捕获封装,内部校验直接抛illegalargumentexception;npe属bug不捕获,error日志须含traceid、用户id、入参摘要。

一、明确宣讲目标:不是讲语法,而是统一团队认知
重点不在于复述 Exception 和 RuntimeException 的继承关系,而是让开发、测试、运维理解:为什么同一类空指针,在支付模块要抛出业务异常并记录 warn,在工具类中却应快速 fail-fast 不捕获?核心是建立「异常代表什么、日志说明什么、谁来关注、何时介入」的共识。
二、异常规范:聚焦三个关键决策点
用实际代码场景带出判断逻辑,避免抽象定义:
- 该不该捕获? —— 外部系统调用(如 HTTP 请求)必须捕获并转为受检异常或封装后的业务异常;内部方法参数校验失败(如 ID ≤ 0)直接 throw IllegalArgumentException,不 try-catch
- 该不该往上抛? —— Service 层不吞异常;Controller 层统一用 @ExceptionHandler 处理,返回标准错误码和提示,不把原始堆栈暴露给前端
- 该用哪种异常? —— 业务规则失败(如“余额不足”)用自定义 Checked 异常(如 InsufficientBalanceException);程序逻辑错误(如 NPE、ArrayIndexOutOfBoundsException)属于 Bug,不捕获、不包装、让其崩溃并靠日志定位
三、日志规范:围绕「可查、可溯、可读」落地
拒绝“System.out.println”和“log.info(“出错了”)”:
- 级别要精准:info 仅用于关键业务节点(如“订单创建成功,ID=12345”);warn 用于预期外但可恢复的情况(如缓存未命中、降级触发);error 必须伴随完整上下文(traceId、用户ID、入参摘要、异常 cause)
- 内容要结构化:禁用字符串拼接日志(log.info("处理用户" + userId + "失败")),改用占位符(log.error("订单支付失败,orderNo={}, userId={}", orderNo, userId))
- 敏感信息要过滤:手机号、身份证、银行卡号等字段在打日志前脱敏(如 138****1234),配置 logback 的 MaskingPatternLayout 或自定义 Appender
四、协同动作:让规范真正跑起来
单靠文档无法落地,需配套机制:
- 在 CI 流程中加入日志扫描(如使用 Log4j2 的 Lookups 检测未脱敏字段)、异常吞没检测(FindBugs/SpotBugs 规则)
- 提供标准模板:Controller 全局异常处理器代码片段、常用业务异常类骨架、logback-spring.xml 推荐配置
- 设立「异常日志看板」:聚合 error 日志 Top10、慢请求关联异常率、各服务 warn/error 比率趋势,每周同步给研发负责人
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











