推荐在自定义异常类中通过构造函数传入错误码和动态参数,延迟至getMessage()时格式化消息,统一管理错误码(枚举/常量)、支持国际化与占位符命名,配合全局异常处理器返回标准响应。

在 Java 中,throw 抛出自定义业务异常时,推荐通过构造函数将错误码和动态参数一并传入异常类,再由异常类统一管理格式化逻辑,避免在 throw 处拼接字符串或硬编码消息。
定义带错误码和参数的自定义异常类
继承 RuntimeException(或 Exception),提供含错误码、错误消息模板、可变参数的构造方法。错误消息使用 String.format 或更安全的 MessageFormat 进行延迟格式化(即在调用 getMessage() 时才格式化),确保异常创建轻量且支持国际化扩展。
- 错误码建议用枚举或常量类统一管理(如
ErrorCode.USER_NOT_FOUND) - 消息模板中用
%s占位符,与传入参数顺序对应 - 构造函数中只保存原始参数,不立即格式化,提升性能并便于日志/序列化
构造函数中保存参数,重写 getMessage() 实现动态格式化
在异常类中缓存错误码、消息模板和参数数组,重写 getMessage() 方法,在首次调用时执行格式化。这样既保持异常对象不可变,又支持运行时注入上下文值(如用户名、订单号)。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 示例:
new BizException(ErrorCode.ORDER_INVALID, "订单 %s 不存在", orderId) -
getMessage()内部调用String.format(template, args)返回最终消息 - 提供
getErrorCode()方法供外部提取错误码,便于统一处理(如网关返回 JSON 错误结构)
配合统一异常处理器提取和响应
在 Spring Boot 等框架中,用 @ControllerAdvice + @ExceptionHandler 捕获自定义异常,从中取出错误码和格式化后的消息,组装标准响应体(如 {"code": "ORDER_INVALID", "message": "订单 ABC123 不存在"})。
立即学习“Java免费学习笔记(深入)”;
- 避免在控制器里手动
try-catch和重复构建响应 - 可结合 Locale 支持多语言:将消息模板外置到 properties 文件,用
MessageSource替代硬编码模板 - 参数值应做基础校验(如非 null),防止格式化时报
IllegalArgumentException
进阶:支持占位符命名与类型安全(可选)
若需更清晰的参数语义(如 "用户 {username} 余额不足"),可用开源库如 java.text.MessageFormat 或引入 slf4j 风格的 {} 占位符(借助 org.apache.commons.text.StringSubstitutor 或自定义解析)。
- 例如:
new BizException(ErrorCode.INSUFFICIENT_BALANCE, "用户 {name} 余额不足,当前 {balance}", Map.of("name", "张三", "balance", "¥10.5")) - 此时构造函数接收
Map<String, Object>,getMessage()中按 key 替换,增强可读性和维护性 - 注意:避免在异常中存储敏感数据(如密码、身份证号),参数仅用于日志和前端提示

















