Java中Assert默认不支持自定义异常,但可通过if+throw、封装带Supplier的校验工具类、Optional.orElseThrow等方式实现;严禁在生产代码中使用JUnit Assertions。

Java 中的 Assert(如 Spring 的 org.springframework.util.Assert 或 JUnit 的 org.junit.jupiter.api.Assertions)默认抛出的是 IllegalArgumentException、IllegalStateException 或 AssertionError,不支持直接指定任意自定义异常类型。但可以通过组合方式实现“条件不满足时抛出自定义异常”的效果。
使用 Spring Assert 并手动 throw 自定义异常
Spring 的 Assert 类主要用于快速失败检查,本身不支持传入自定义异常构造逻辑,但可配合 if + throw 使用,语义清晰且常用:
- 先用
Assert.isTrue(...)或Assert.notNull(...)做校验 - 校验失败时,它会抛出固定异常;若要抛自定义异常,就不用它的断言方法,改用普通 if 判断
- 例如:推荐做法 —— 直接写条件判断 + throw
示例:
if (userId == null) {
throw new BusinessException("用户ID不能为空");
}
if (userId <= 0) {
throw new BusinessException("用户ID必须为正整数");
}
封装通用校验方法支持自定义异常
为避免重复写 if-throw,可封装一个工具类,将条件判断和异常构造解耦:
立即学习“Java免费学习笔记(深入)”;
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 定义一个静态方法,接收布尔表达式、错误消息、异常 Supplier
- 内部判断条件,不满足则通过 Supplier 创建并抛出异常
- 这样既复用逻辑,又完全控制异常类型和构造方式
示例工具方法:
public class Asserts {
public static <T extends Throwable> void isTrue(boolean expression,
String message, Supplier<T> exceptionSupplier) throws T {
if (!expression) {
throw exceptionSupplier.get();
}
}
}
调用方式:
Asserts.isTrue(userId != null, "用户ID为空",
() -> new BusinessException("E001", "用户ID不能为空"));
利用 Optional + orElseThrow(适合单条件非空校验)
对对象非空校验,可结合 Optional 实现简洁写法,且天然支持自定义异常:
Optional.ofNullable(obj).orElseThrow(() -> new XxxException(...))- 适合判空场景,语义明确,一行解决
- 注意:不适用于复合条件(如数值范围、字符串非空且长度合法等)
示例:
User user = userRepository.findById(userId);
User safeUser = Optional.ofNullable(user)
.orElseThrow(() -> new UserNotFoundException("用户不存在,ID:" + userId));
避免误用 JUnit Assert(仅用于测试)
JUnit 的 Assertions(如 assertTrue、assertNotNull)设计目标是单元测试断言,抛出的是 AssertionError,且在生产环境默认禁用(JVM 参数 -ea 才启用)。因此:
- 切勿在业务代码中依赖 JUnit Assert 做运行时校验
- 它不支持自定义异常,也不保证在所有环境下生效
- 生产级校验应使用 Spring Assert、Apache Commons Lang 或自定义逻辑

















