陷阱使用斷言進行引數或使用者輸入驗證

StackOverflow 上偶爾會出現的問題是,使用 assert 驗證提供給方法的引數是否合適,甚至是使用者提供的輸入。

簡單的答案是它不合適。

更好的選擇包括:

  • 使用自定義程式碼丟擲 IllegalArgumentException。
  • 使用 Google Guava 庫中提供的 Preconditions 方法。
  • 使用 Apache Commons Lang3 庫中提供的 Validate 方法。

這就是 Java 語言規範(JLS 14.10,Java 8) 就此問題提出的建議:

通常,在程式開發和測試期間啟用斷言檢查,並在部署時禁用斷言檢查以提高效能。

由於斷言可能被禁用,因此程式不得假定將評估斷言中包含的表示式。因此,這些布林表示式通常應該沒有副作用。評估此類布林表示式不應影響評估完成後可見的任何狀態。斷言中包含的布林表示式具有副作用並非違法,但通常不合適,因為它可能導致程式行為根據斷言是啟用還是禁用而變化。

鑑於此,斷言不應用於公共方法中的引數檢查。引數檢查通常是方法合同的一部分,並且必須維護此合同是否啟用斷言。

使用斷言進行引數檢查的第二個問題是錯誤的引數應該導致適當的執行時異常(例如 IllegalArgumentExceptionArrayIndexOutOfBoundsExceptionNullPointerException)。斷言失敗不會引發適當的異常。同樣,在公共方法上使用斷言進行引數檢查並不違法,但這通常是不合適的。AssertionError 的目的永遠不會被捕獲,但是有可能這樣做,因此 try 語句的規則應該處理 try 塊中出現的斷言,類似於當前對 throw 語句的處理。