傳統斷言只能檢查「當下」的狀態,無法表達「隨時間演變」的不變量。時態邏輯引入 Always、Sometime、Next、Until 等算子,能精確描述系統在執行軌跡上的屬性,從而捕捉常規單元測試難以覆蓋的深層錯誤模式。
將樹葉表示為左右子節點為 null 的節點,極易在遞歸遍歷時觸發 NPE。重構為 Composite 模式(Leaf/Branch 分離)後,在 Branch 的 left/right 字段加上 Always{left != null} 斷言,編譯期即可阻斷錯誤構造。
數據庫中違反業務約束的數據(如年齡為負、婚姻關係非對稱)可能由不可控客戶端寫入。在關鍵表上聲明 ForAll x in Employees . Always{Age >= 0}、Always{isMarried(x,y) implies isMarried(y,x)},運行時即可快速定位違規數據源。
當打開文件與關閉文件分散在不同方法,控制流極易導致資源未釋放或重複釋放。在獲取資源處放置斷言:Always{acquired implies (Released until Reacquired)},可強制檢測釋放邏輯缺失。
在每個 wait() 處斷言 Always{wait() implies Sometime{notify()}},若程序終止前等待未被喚醒,將報錯提示潛在死鎖。
為 Stack 接口添加強時態契約:
Always{push(x) implies {{top() == x} until {push(y) || pop()}}}
Always{isEmpty() implies {{!pop()} until {push(x)}}}
Always{{length == n && push(x)} implies {Next{length == n+1}}}
任何違背 LIFO 語義的實現(如誤用 Queue)在運行時即會被攔截。
每條時態斷言等價於多條傳統斷言的組合,卻更簡潔、更精準。它們不僅是文檔,更是可執行的運行時守衛。結合自動化斷言檢測工具(如 JUnit 衍生框架),可構建「自我驗證」的代碼庫。下一期將探討如何自動挖掘代碼中隱含的斷言。