异常信息必须包含上下文,不能只抛 new RuntimeException(“出错”);应拼入关键变量、状态或输入值,并用带 cause 的构造函数保留原始堆栈;日志级别需匹配异常性质,WARN 用于业务校验失败,ERROR 用于系统级故障。
异常信息必须包含上下文,不能只抛 new RuntimeException("出错")
Java里最常犯的错误是用空泛字符串构造异常,比如 throw new IllegalArgumentException("参数错误")。这种写法在日志里完全无法定位问题:哪个方法?传了什么值?执行到哪一行?
正确做法是在消息中拼入关键变量、状态或输入值,例如:
throw new IllegalArgumentException("userId 为 null,调用方: " + Thread.currentThread().getStackTrace()[1].getMethodName());
更稳妥的方式是用 String.format 或现代 Java 的文本块 + 字符串拼接,避免空指针或格式错乱。注意别把敏感字段(如密码、token)打到日志里。
用 initCause() 或构造函数链式包装异常,保留原始堆栈
捕获异常后直接 throw new RuntimeException("xxx") 会丢失原始异常的堆栈和类型,导致无法判断是 NPE、SQLTimeout 还是网络中断。
立即学习“Java免费学习笔记(深入)”;
应该用带 cause 的构造函数,例如:
catch (SQLException e) {
throw new ServiceException("查询用户失败,sqlId=" + sqlId, e);
}
或者显式调用 initCause()(仅限无对应构造函数的老异常类)。这样日志打印时能展开 Cause by: 链,IDE 调试时也能逐层点开。
常见陷阱: