JDK 1.4 引入 assert 關鍵字,為開發階段的契約檢查、不變量驗證提供原生支持。斷言預設關閉,運行時零開銷;啟用後可作為「開發期守衛」,生產環境關閉不影響性能。本文詳解語法、編譯運行參數、最佳實踐與常見陷阱。
assert Boolean表達式; // 簡單斷言
assert Boolean表達式 : "詳細錯誤信息"; // 帶診斷信息的斷言
true → 繼續執行false → 拋出 AssertionError(Error,非 Exception),第二種形式以診斷信息構造異常對象| 操作 | 命令 | 說明 |
|---|---|---|
| 編譯 | javac -source 1.4 AssertExample.java | 必須指定 -source 1.4 才識別 assert 關鍵字 |
| 啟用斷言運行 | java -ea AssertExample 或 java -enableassertions | 啟用所有類斷言;可限定包/類:-ea:com.myapp... |
| 禁用斷言運行 | java -da AssertExample | 預設行為,顯式禁用可覆蓋類路徑默認啟用 |
| 系統類啟用 | java -esa / -dsa | 啟用/禁用系統類斷言(慎用) |
public class AssertExample {
public static void main(String[] args) {
int x = 10;
if (args.length > 0) {
try { x = Integer.parseInt(args[0]); }
catch (NumberFormatException ignored) {}
}
System.out.println("Testing assertion that x == 10");
assert x == 10 : "Our assertion failed: x=" + x;
System.out.println("Test passed");
}
}
運行 java -ea AssertExample 5 輸出:
Testing assertion that x == 10
Exception in thread "main" java.lang.AssertionError: Our assertion failed: x=5
at AssertExample.main(AssertExample.java:12)
boolean enabled = false;
// ...
assert enabled = true; // 錯誤!斷言關閉時賦值不執行,邏輯崩塌
鐵律:斷言表達式絕不能修改程序狀態。只能做純布爾檢查。
public class AssertCheck {
public static void main(String[] args) {
boolean assertEnabled = false;
assert assertEnabled = true; // 僅在啟用時執行
if (!assertEnabled) {
throw new RuntimeException("斷言未啟用,測試無效!");
}
System.out.println("斷言已啟用,繼續測試...");
}
}
無 -ea 運行將拋出 RuntimeException,保證測試環境正確性。
public void setRate(int rate) { assert rate > 0 && rate <= 100; ... }assert result != null : "計算結果不應為空";assert size() >= 0 : "size 不能為負";default: assert false : "未處理的枚舉值: " + enumVal;IllegalArgumentException),保證契約在生產環境也生效| 維度 | 斷言 | 單元測試 | 日誌 |
|---|---|---|---|
| 執行階段 | 開發/測試運行時 | 構建/測試階段 | 全生命週期 |
| 失敗行為 | 拋 Error 終止 | 標紅報告 | 記錄繼續 |
| 生產開銷 | 零(關閉) | 不部署 | 有(I/O) |
| 適用場景 | 內部不變量、契約 | 功能正確性 | 業務追蹤、審計 |
善用斷言,讓 Bug 在開發期「暴斃」,而非帶著偽裝潛伏到生產環境。