java断言仅用于开发调试阶段暴露本不该发生的逻辑错误,生产环境默认关闭;必须显式加-ea参数启用,适用私有方法内部状态、循环不变量等契约检查,不可有副作用,失败抛出不可捕获的assertionerror。

Java断言(assert)不是用来处理用户输入或外部异常的,它的核心作用是在开发阶段主动暴露**本不该发生**的逻辑错误——比如算法前提崩塌、状态机进入非法状态、私有方法内部契约被破坏。用对了,它能成为你代码的“逻辑探针”;用错了,上线后就等于没写。
只在开发/测试阶段启用,生产环境默认不生效
断言默认被JVM禁用,哪怕写了assert x != null;,不加-ea参数就完全不执行。这意味着:
- IDE运行时要手动在Run Configuration → VM options里填
-ea(IntelliJ/Eclipse都需配置,否则调试时也看不到断言效果) - Gradle测试需显式开启:
test { jvmArgs = ['-ea'] } - 生产打包或容器启动时,切勿加
-ea——AssertionError是Error子类,设计上就不该被捕获或恢复,强行启用会把本该快速失败的问题拖成静默故障
适用场景:验证内部不变式,而非业务校验
断言适合声明“这里必须为真,否则整个模块已不可信”的条件,典型例子包括:
- 私有方法执行前/后状态检查:
assert list.size() == oldSize + 1 : "add() should increase size by 1"; - 循环不变量验证:
assert maxSoFar >= array[i] : "max invariant broken at index " + i; - 算法前提断言(如二分查找要求数组已排序):
assert isSorted(arr) : "array must be sorted for binarySearch"; - 枚举状态流转合法性:
assert state == State.READY || state == State.PROCESSING : "illegal state transition";
⚠️ 注意:公共方法入口的参数校验(如public void process(String input))绝不能用assert input != null,而应抛出IllegalArgumentException——因为调用方可能是其他模块,这属于明确的业务契约,不是内部调试假设。
写法必须干净,禁止副作用
断言表达式在生产环境会被JVM跳过,所以任何带副作用的代码会导致行为不一致:
- ❌ 错误:
assert map.remove("key") != null;→ 上线后这行不执行,键还在map里 - ❌ 错误:
assert logger.info("checking value: " + x);→ 上线后日志消失,且logger.info()可能返回void,语法都不合法 - ✅ 正确:
assert x > 0 : "x must be positive, got " + x;→ 纯布尔判断 + 静态字符串拼接
失败即终止,不要捕获AssertionError
AssertionError继承自Error,代表程序已处于“无法继续信任”的状态。因此:
- ❌ 不要写
try { assert ... } catch (AssertionError e) { ... } - ❌ 不要在方法签名中声明
throws AssertionError - ✅ 正确做法是让JVM直接崩溃,配合日志和堆栈快速定位问题根源——这正是断言的设计目的:把“理论上不可能”的bug变成“立刻可见”的现场
如果发现自己想“兜住”断言失败,说明这里本该是业务异常处理,该换用Objects.requireNonNull()或自定义RuntimeException。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











