1. 介绍
Java 中的 assert
关键字允许开发者快速验证程序中的某些假设或状态。本文将深入探讨如何使用 Java 的 assert
关键字,以及在实际开发中的注意事项。
2. Java 断言的历史
Java 的 assert
关键字自 Java 1.4 版本引入,已经存在相当长时间。然而,它仍是一个鲜为人知的关键字,能显著减少样板代码并提升代码可读性。
例如,在代码中我们经常需要验证某些可能影响程序正常运行的条件。通常我们会这样写:
Connection conn = getConnection();
if(conn == null) {
throw new RuntimeException("Connection is null");
}
使用断言后,我们可以用单个 assert
语句替代整个 if-throw
结构:
Connection conn = getConnection();
assert conn != null;
3. 启用 Java 断言
由于 Java 断言使用 assert
关键字,无需导入任何库或包。但需要注意:
⚠️ 向后兼容性问题:在 Java 1.4 之前,"assert" 可以作为变量名、方法名等合法标识符。这可能导致旧代码在新 JVM 上运行时产生命名冲突。
因此,JVM 默认禁用断言验证。必须通过命令行参数显式启用:
- 使用
-enableassertions
或其简写-ea
java -ea com.baeldung.assertion.Assertion
上述命令为所有类启用断言。也可针对特定包或类启用:
java -ea:com.baeldung.assertion... com.baeldung.assertion.Assertion
同样,可通过 -disableassertions
或 -da
禁用特定包/类的断言。四种参数可组合使用。
4. 使用 Java 断言
添加断言只需使用 assert
关键字并跟随一个布尔条件:
public void setup() {
Connection conn = getConnection();
assert conn != null;
}
Java 还提供第二种语法,可附加错误信息字符串:
public void setup() {
Connection conn = getConnection();
assert conn != null : "Connection is null";
}
两种方式都在验证外部资源连接是否返回非空值。若值为 null
,JVM 会**自动抛出 AssertionError
**。
第二种方式会在异常堆栈中显示附加信息,便于调试。启用断言后的运行结果示例:
Exception in thread "main" java.lang.AssertionError: Connection is null
at com.baeldung.assertion.Assertion.setup(Assertion.java:15)
at com.baeldung.assertion.Assertion.main(Assertion.java:10)
5. 处理 AssertionError
AssertionError
继承自 Error
,而 Error
继承自 Throwable
。这意味着 AssertionError
是非受检异常。
因此:
- 使用断言的方法无需声明抛出该异常
- 调用代码不应尝试捕获它
❌ 重要原则:AssertionError
用于表示程序中不可恢复的条件,永远不要尝试处理或恢复这类错误。
6. 最佳实践
使用断言时最关键的是:断言可能被禁用,切勿假设它们一定会执行。因此需牢记以下要点:
✅ 必须检查的场景:
- 始终检查空值和空的 Optional(在适当位置)
- 避免在公共方法输入验证中使用断言,改用
IllegalArgumentException
或NullPointerException
- 不要在断言条件中调用方法,应先将方法结果赋给局部变量再断言
✅ 适用场景:
- 永远不会执行的代码路径(如 switch 的 default 分支)
- 永不终止的循环之后
- 内部不变量验证
❌ 避免场景:
- 公共 API 的参数校验
- 可能产生副作用的条件检查
- 需要保证执行的关键逻辑
7. 总结
Java 的 assert
关键字虽已存在多年,仍是语言中鲜为人知的特性。它能有效减少样板代码,提升可读性,并在开发早期帮助识别缺陷。
但请牢记:断言默认禁用,切勿在代码中依赖其必然执行。合理使用断言能让代码更简洁,但滥用可能导致生产环境出现意外行为。
完整源代码可在 GitHub 获取。