J2SE 1.4 引入 assert 關鍵字,是 Java 語言層面最大的創新之一。斷言作為經典的調試/測試技術,早存在於 C/C++/Eiffel 等語言。理論上可用於程序正確性證明,但工程實踐中主要作為 開發期/測試期的防禦性檢查機制。
// 形式 1:簡單斷言
assert booleanExpression;
// 形式 2:帶詳細訊息斷言
assert booleanExpression : detailExpression;
booleanExpression:任意布林表達式detailExpression:任意基本類型或物件 (傳遞給 AssertionError 建構子)| 斷言狀態 | booleanExpression 為 true | booleanExpression 為 false |
|---|---|---|
| 啟用 (-ea) | 無事發生,繼續執行 | 拋出 AssertionError (攜帶 detailExpression 值) |
| 停用 (預設/-da) | 語句完全不執行,零開銷 | |
detailExpression 僅在斷言失敗時求值 (短路語義)assert 為關鍵字,編譯需指定源版本:
javac -source 1.4 MyClass.java
舊代碼中使用 assert 作為識別碼會導致編譯錯誤。
# 全域啟用
java -ea MyClass
java -enableassertions MyClass
# 全域停用 (預設)
java -da MyClass
# 特定包/類啟用
java -ea:com.myapp... MyClass
java -ea:MyClass
# 系統類別啟用 (需額外標誌)
java -esa:java.util... MyClass
assert 0 < value : "value=" + value;
assert ref != null : "ref doesn't equal null";
assert isBalanced();
public void setRate(int rate) {
// 前置條件
assert rate > 0 && rate <= 100 : "Invalid rate: " + rate;
this.rate = rate;
// 後置條件 (私有方法驗證內部狀態)
assert invariant();
}
private boolean invariant() {
return rate > 0 && rate <= 100;
}
switch (status) {
case ACTIVE: handleActive(); break;
case INACTIVE: handleInactive(); break;
default:
assert false : "Unexpected status: " + status;
}
| 維度 | 斷言 | 異常 |
|---|---|---|
| 目的 | 檢查「不可能發生」的程序邏輯錯誤 (Bug) | 處理「可能發生」的運行時異常情況 |
| 目標受眾 | 開發人員/測試人員 | 最終用戶/上層調用者/錯誤處理機制 |
| 生產環境 | 關閉 (零開銷) | 必須啟用並妥善處理 |
| 可恢復性 | 不可恢復 (表示程序邏輯缺陷) | 可恢復/可處理/可轉換 |
| 參數驗證 | 不適用於 public 方法參數檢查 | public 方法必須驗證參數並拋出異常 |
// 錯誤:public 方法參數驗證用斷言
public void setName(String name) {
assert name != null; // 生產環境失效!
this.name = name;
}
// 正確:拋出異常
public void setName(String name) {
if (name == null) throw new IllegalArgumentException("name cannot be null");
this.name = name;
}
-ea 參數Java 斷言機制以 assert 關鍵字提供零開銷的開發期防禦性檢查。正確理解其「開發期啟用、生產期關閉」的生命週期,區別於異常處理機制,將斷言應用於內部不變量驗證與邏輯錯誤捕獲,能顯著提升代碼質量與除錯效率。