例外處理
1. 【強制】不要捕獲Java 類別庫中定義的繼承自RuntimeException 的運行時異常類,如:IndexOutOfBoundsException / NullPointerException,這類異常由程式設計師預先檢查來規避,保證程序健壯性。
正例: if(obj != null) {...}
反例: try { obj.method( ) } catch(NullPointerException e){...}
2. 【強制】異常不要用來做流程控制,條件控制,因為異常的處理效率比條件分支低。
3. 【強制】對大段程式碼進行 try - catch ,這是不負責任的表現。 catch 時請分辨穩定程式碼和非穩定程式碼,穩定程式碼指的是無論如何都不會出錯的程式碼。對於非穩定程式碼的 catch 盡可能進行區分異常類型,再做對應的異常處理。
4. 【強制】捕獲異常是為了處理它,不要捕獲了卻什麼都不處理而拋棄之,如果不想處理它,請將該異常拋給它的調用者。最外層的業務使用者,必須處理異常,將其轉化為用戶可以理解的內容。
5. 【強制】有 try 區塊放到了交易代碼中, catch 異常後,如果需要回滾事務,一定要注意手動回滾事務。
6. 【強制】 finally 區塊必須對資源物件、串流物件進行關閉,有異常也要做 try - catch 。
說明:如果 JDK 7,可以使用 try - with - resources 方式。
7. 【強制】不能在 finally 區塊中使用 return , finally 區塊中的 return 返回後方法結束執行,不會再執行 try 區塊中的 return 語句。
8. 【強制】捕獲異常與拋異常,必須是完全匹配,或者捕獲異常是拋異常的父類。
說明:如果預期對手拋的是繡球,實際接到的是鉛球,就會產生意外狀況。
9. 【建議】方法的回傳值可以為 null ,不強制傳回空集合,或是空物件等,必須加入註解充分說明什麼情況下會傳回 null 值。呼叫方需要進行 null 判斷防止 NPE 問題。
說明:本規約明確防止 NPE 是呼叫者的責任。即使被呼叫方法傳回空集合或空對象,對呼叫者來說,也並非高枕無憂,必須考慮到遠端呼叫失敗,運行時異常等場景傳回 null 的情況。
10. 【推薦】防止 NPE ,是程式設計師的基本修養,注意 NPE 產生的場景:
1 ) 傳回類型為包裝資料型,有可能是 null ,傳回 int 值時要注意判空。
反例: public int f() { return Integer 物件}; 若為 null ,自動解箱拋 NPE 。
2 ) 資料庫的查詢結果可能為 null 。
3 ) 集合裡的元素即使 isNotEmpty ,取出的資料元素也可能為 null 。
4 ) 遠端呼叫返回對象,一律要求進行 NPE 判斷。
5 ) 對於 Session 中所獲得的數據,建議 NPE 檢查,避免空指標。
6 ) 級聯調用 obj . getA() . getB() . getC(); 一連串調用,易產生 NPE 。
11. 【推薦】在程式碼中使用“拋異常”或“返回錯誤碼”,對於公司外的http / api 開放介面必須使用“錯誤碼” ;而應用內部推薦異常拋出;跨應用間RPC 呼叫優先考慮使用Result 方式,封 裝置isSuccess 、「錯誤碼」、「錯誤簡短訊息」。
說明:關於RPC 方法回傳方式使用Result 方式的理由:
1 ) 使用拋例外回傳方式,呼叫方如果沒有被捕獲到就會產生運行時錯誤。
2 ) 如果不加棧訊息,只是 new 自訂異常,加入自己的理解的 error message ,對於呼叫端解決問題的幫助不會太多。如果加了堆疊訊息,在頻繁呼叫出錯的情況下,資料序列化和傳輸的效能損耗也是問題。
12. 【推薦】定義時區分unchecked / checked 異常,避免直接使用RuntimeException 拋出,更不允許拋出Exception 或Throwable ,應使用有業務意義的自訂異常。推薦業界已定義過的自訂異常,如: DAOException / ServiceException 等。
13. 【參考】避免出現重複的程式碼 (Don ’ t Repeat Yourself) ,即 DRY 原則。
說明:隨意複製和貼上程式碼,必然會導致程式碼的重複,在以後需要修改時,需要修改所有的副本,容易遺漏。必要時抽取共通方法,或抽象公共類,甚至是共用模組。
正例:一個類別中有多個public 方法,都需要進行數行相同的參數校驗操作,這個時候請抽取:
# private boolean checkParam(DTO dto){...}