Java断言使用assert关键字而非Assert类,专用于开发期防御性编程,校验内部逻辑契约,生产环境默认关闭;须避免副作用,不可替代输入校验或异常处理。

Java 中没有 Assert 类——这是常见误解。Java 的断言机制基于 assert 关键字,而非某个可实例化的 Assert 类(如 JUnit 中的 org.junit.Assert 是测试专用工具,**不可用于生产代码的防御性编程**)。真正用于防御式编程的,是 JVM 原生支持的 assert 语句,它轻量、开发期启用、生产环境默认关闭,专为捕捉“绝不该发生”的逻辑缺陷。
用对 assert:只校验内部契约,不处理外部风险
断言不是异常处理的替代品,而是开发阶段的逻辑守门员。它适用于那些本应由程序员保证、一旦失败就说明代码写错了的情况:
- 方法执行前,对象已正确初始化(如
assert this.initialized;) - 私有辅助方法的参数符合隐含约定(如递归终止条件、中间计算结果非负)
- 循环不变式成立(如每次迭代后数组前 i 个元素已排序)
- switch 分支已覆盖全部枚举值,且 default 分支仅作兜底断言(
default: assert false : "unreachable";)
正确写法:避免副作用,消息要具体
断言表达式必须是纯判断,不能触发状态变更或 I/O:
- ❌ 错误:
assert list.remove(0) != null : "list was empty";(关闭断言时 remove 不执行,逻辑被跳过) - ✅ 正确:
assert !list.isEmpty() : "list must not be empty before pop"; - 消息建议包含“为什么重要”和“当前值”,例如:
assert count >= 0 : "count corrupted: got " + count;
启用与禁用:开发开,上线关
断言默认关闭,需显式启用才能生效:
立即学习“Java免费学习笔记(深入)”;
- 运行时开启:启动 JVM 时加参数
-ea(或-enableassertions),如java -ea MyApp - 按包/类精细控制:
-ea:com.example.service...或-da:com.example.util... - 生产环境务必保持默认关闭——既避免性能损耗,也防止暴露内部实现细节
别混淆:assert ≠ 输入校验,更不是 try-catch 替代
用户输入、文件内容、网络响应等外部数据,永远不可信,必须用显式校验 + 异常抛出:
- ✅ 正确处理外部输入:
if (userId - ❌ 错误依赖断言:
assert userId > 0 : "invalid user id";(上线后失效,非法输入直接穿透) - 断言失败抛
AssertionError,属于Error子类,不应被捕获;而业务异常应抛RuntimeException或其子类,并由上层统一处理



















