1. 程式人生 > >【Java開發手冊之異常日誌(一)】異常處理

【Java開發手冊之異常日誌(一)】異常處理

  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){…}