在閱讀 JDK 源碼時,你一定會頻繁遇到 assert 關鍵字。作為 JDK 1.4 引入的特性,assert(斷言)雖然不常用於業務代碼,卻是框架、工具類、基礎庫開發中實現契約式編程、提升代碼健壯性的關鍵工具。本文將從語法、啟用機制、設計哲學、最佳實踐四個維度深度解析 assert。
斷言:開發者對程序運行狀態做出的「必須為真」的假設。若假設不成立,說明代碼邏輯存在缺陷,應立即拋出錯誤終止執行,而非靜默繼續導致不可預期後果。
assert vt. 維護、堅持、斷言、主張// 形式 1:簡單斷言 assert 布爾表達式; // 形式 2:帶詳細信息斷言 assert 布爾表達式 : 表達式2; // 表達式2 結果將作為 AssertionError 的構造參數
| 條件值 | 形式 1 行為 | 形式 2 行為 |
|---|---|---|
| true | 繼續執行後續代碼 | 繼續執行,表達式2 不求值 |
| false | 拋出 AssertionError(無消息) | 求值表達式2,結果封裝進 AssertionError 拋出 |
public class AssertDemo {
public static void main(String[] args) {
// 啟用斷言後運行:java -ea AssertDemo
assert 1 == 1; // true,正常通過
System.out.println("A Go!");
System.out.println("\n-----------------------------------------------\n");
assert 1 != 1 : "Wrong"; // false,拋出 AssertionError: Wrong
System.out.println("B Go!"); // 不會執行
}
}
assert 面向開發/測試階段,生產環境默認禁用以避免性能開銷。這體現了「零成本斷言」理念:代碼中保留檢查邏輯,部署時通過 JVM 參數控制是否激活。
| 環境 | 啟用命令 | 禁用命令 |
|---|---|---|
| 命令行 | java -ea ClassName 或 java -enableassertions ClassName | java -da ClassName |
| Eclipse | Run Configurations → Arguments → VM arguments: -ea | VM arguments: -da |
| IntelliJ IDEA | Edit Configurations → VM options: -ea | VM options: -da |
| 維度 | assert | if + throw |
| 語義 | 契約/不變量:正常邏輯不可能違反 | 業務邏輯:可能發生的異常情況 |
| 異常類型 | AssertionError (Error 體系,不可恢復) | Exception (可捕獲處理) |
| 性能影響 | 生產環境零開銷(字節碼不執行) | 始終執行判斷 |
| 代碼整潔度 | 核心邏輯中不混雜防禦代碼 | 大量 if 降低可讀性 |
| 繼承性 | 無繼承性(父類啟用不影響子類) | 正常方法繼承 |