应使用自定义异常:当内置异常无法准确表达业务含义、调用方需差异化处理、或监控/日志需按业务维度归类时,如phonealreadyexistsexception明确语义,支持结构化信息携带、精准错误码映射与框架集成。

当内置异常无法准确表达业务含义、调用方需要差异化处理、或监控/日志需按业务维度归类时,就该用自定义异常。
业务语义不清晰时必须自定义
比如用户注册时手机号已存在,抛 IllegalArgumentException("phone exists") 和参数为空、格式错误都混在同一个异常类型里。日志看不出是校验失败还是业务冲突,前端也无法区分展示“手机号已被占用”和“请输入手机号”。换成 PhoneAlreadyExistsException,名称即含义,一眼定位问题场景。
调用方要执行不同恢复逻辑
下游系统对不同错误的响应策略不同:
- 余额不足(InsufficientBalanceException)→ 触发充值提醒短信
- 订单已取消(OrderCancelledException)→ 自动重试或标记为不可操作
- 库存不足(StockShortageException)→ 切换备用商品或降级返回兜底页
如果全靠 RuntimeException 或字符串匹配 message,容易漏判、误判,且违反开闭原则。
需要携带结构化业务信息
内置异常只提供 message 和 cause,但线上排障常需快速获取:errorCode(如 4001)、traceId(全链路追踪)、orderId 或 skuId 等上下文字段。自定义异常可直接封装这些属性,避免日志拼接、解析失败或字段缺失。
统一错误码体系与框架集成需求
Spring 的 @ExceptionHandler 按异常类型注册处理器;网关或 RPC 框架依赖异常类型映射 HTTP 状态码(如 @ResponseStatus(code = HttpStatus.CONFLICT))。若没有独立异常类,只能写一堆 if (e.getMessage().contains("xxx")),既脆弱又难维护。错误码 40001(优惠券过期)、40002(库存不足)必须对应不同异常类型,才能被精准识别和路由。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











