assert 關鍵字自 JDK 1.4 引入,用於開發階段的假設檢查。本文系統梳理語法、運行機制、四大陷阱、適用場景與現代替代方案。
// 形式一:簡單斷言
assert booleanExpression;
// 形式二:帶訊息斷言
assert booleanExpression : "錯誤訊息表達式";
true:程式繼續執行false:拋出 AssertionError(第二形式附帶訊息)-ea 或 -enableassertions 啟用assert 為測試/調試設計,若用於業務邏輯(如參數校驗),關閉後邏輯缺失導致 Bug 隱匿。Error 而非 Exception,無法被常規 catch 捕獲,生產環境不可接受。assert list.remove(x)),關閉後副作用消失,行為不一致。precondition,出口檢查 postcondition-ea,作為輕量級斷言(JUnit assertTrue 更豐富)default: in switch on enum)public static List<Integer> quickSort(List<Integer> list) {
assert list != null : "輸入列表不能為 null"; // 文檔化前置條件
// 分配臨時空間...
for (int i : list) { /* 排序邏輯 */ }
assert isSorted(list) : "排序後列表應有序"; // 文檔化後置條件
return list;
}
| 方案 | 優點 | 缺點 | 推薦場景 |
|---|---|---|---|
| JUnit / AssertJ | 豐富斷言、可讀性強、測試報表整合 | 僅測試代碼 | 單元/整合測試 |
| Objects.requireNonNull / checkIndex | 標準庫、拋 NPE/IAE 可捕獲、生產有效 | 功能有限 | 參數校驗、邊界檢查 |
| Spring Validation (JSR-380) | 聲明式、國際化、分組驗證 | 需框架支援 | Web 入參、DTO 校驗 |
| Guava Preconditions | 流式 API、豐富檢查、生產有效 | 第三方依賴 | 通用防禦性編程 |
| 斷言 | 零依賴、語法內建、文檔化不變量 | 預設關閉、生產失效 | 核心庫內部不變量檢查 |
Objects.requireNonNull、if-check-throw、Validation 框架-eaassert 仍作為可執行文檔說明代碼契約「斷言是給程式設計師看的文檔,不是給用戶看的錯誤處理。」 —— 《Effective Java》