阿里開發手冊泰山版學習筆記十二、異常日誌-異常處理

  1. 【強制】Java 類庫中定義的可以通過預檢查方式規避的 RuntimeException 異常不應該通過
    catch 的方式來處理,比如:NullPointerException,IndexOutOfBoundsException 等等。
    說明:無法通過預檢查的異常除外,比如,在解析字符串形式的數字時,可能存在數字格式錯誤,不得不
    通過 catch NumberFormatException 來實現。
    正例:
if (obj != null) {...}

反例:

try { obj.method(); } catch (NullPointerException e) {}
  1. 【強制】異常不要用來做流程控制,條件控制。
    說明:異常設計的初衷是解決程序運行中的各種意外情況,且異常的處理效率比條件判斷方式要低很多。

  2. 【強制】catch 時請分清穩定代碼和非穩定代碼,穩定代碼指的是無論如何不會出錯的代碼。對於非穩定代碼的 catch 儘可能進行區分異常類型,再做對應的異常處理。
    說明:對大段代碼進行 try-catch,使程序無法根據不同的異常做出正確的應激反應,也不利於定位問題,這是一種不負責任的表現。
    正例:用戶註冊的場景中,如果用戶輸入非法字符,或用戶名稱已存在,或用戶輸入密碼過於簡單,在程序上作出分門別類的判斷,並提示給用戶。

  3. 【強制】捕獲異常是爲了處理它,不要捕獲了卻什麼都不處理而拋棄之,如果不想處理它,請將該異常拋給它的調用者。最外層的業務使用者,必須處理異常,將其轉化爲用戶可以理解的內容。

  4. 【強制】事務場景中,拋出異常被 catch 後,如果需要回滾,一定要注意手動回滾事務。

  5. 【強制】finally 塊必須對資源對象、流對象進行關閉,有異常也要做 try-catch。 說明:如果 JDK7 及以上,可以使用 try-with-resources` 方式。

  6. 【強制】不要在finally 塊中使用 return
    說明:try 塊中的 return 語句執行成功後,並不馬上返回,而是繼續執行 finally 塊中的語句,如果此處存在return語句,則在此直接返回,無情丟棄掉try塊中的返回點。
    反例:

private int x = 0;
public int checkReturn() {
 try {
 // x 等於 1,此處不返回
 return ++x;
 } finally {
 // 返回的結果是 2
 return ++x;
 }
}
  1. 【強制】捕獲異常與拋異常,必須是完全匹配,或者捕獲異常是拋異常的父類。
    說明:如果預期對方拋的是繡球,實際接到的是鉛球,就會產生意外情況。

  2. 【強制】在調用 RPC、二方包、或動態生成類的相關方法時,捕捉異常必須使用 Throwable類來進行攔截。
    說明:通過反射機制來調用方法,如果找不到方法,拋出 NoSuchMethodException。什麼情況會拋出
    NoSuchMethodError 呢?二方包在類衝突時,仲裁機制可能導致引入非預期的版本使類的方法簽名不匹配,或者在字節碼修改框架(比如:ASM)動態創建或修改類時,修改了相應的方法簽名。這些情況,即使代碼編譯期是正確的,但在代碼運行期時,會拋出NoSuchMethodError。

  3. 【推薦】方法的返回值可以爲 null,不強制返回空集合,或者空對象等,必須添加註釋充分說明什麼情況下會返回 null 值。
    說明:本手冊明確防止 NPE 是調用者的責任。即使被調用方法返回空集合或者空對象,對調用者來說,也並非高枕無憂,必須考慮到遠程調用失敗、序列化失敗、運行時異常等場景返回 null 的情況。

  4. 【推薦】防止 NPE,是程序員的基本修養,注意 NPE 產生的場景:
    1) 返回類型爲基本數據類型,return 包裝數據類型的對象時,自動拆箱有可能產生 NPE。
    反例:public int f() { return Integer 對象}, 如果爲 null,自動解箱拋 NPE。
    2) 數據庫的查詢結果可能爲 null。
    3) 集合裏的元素即使 isNotEmpty,取出的數據元素也可能爲 null。
    4) 遠程調用返回對象時,一律要求進行空指針判斷,防止 NPE。
    5) 對於 Session 中獲取的數據,建議進行 NPE 檢查,避免空指針。
    6) 級聯調用 obj.getA().getB().getC();一連串調用,易產生NPE。
    正例:使用 JDK8 的 Optional 類來防止 NPE 問題

  5. 【推薦】定義時區分 unchecked / checked 異常,避免直接拋出 new RuntimeException(),更不允許拋出 Exception 或者 Throwable,應使用有業務含義的自定義異常。推薦業界已定義過的自定義異常,如:DAOException / ServiceException 等。

  6. 【參考】對於公司外的 http/api 開放接口必須使用“錯誤碼”;而應用內部推薦異常拋出;跨應用間 RPC 調用優先考慮使用 Result 方式,封裝 isSuccess()方法、“錯誤碼”、“錯誤簡短信息”;而應用內部推薦異常拋出。
    說明:關於 RPC 方法返回方式使用 Result 方式的理由:
    1)使用拋異常返回方式,調用方如果沒有捕獲到就會產生運行時錯誤。
    2)如果不加棧信息,只是 new 自定義異常,加入自己的理解的 error message,對於調用端解決問題的幫助不會太多。如果加了棧信息,在頻繁調用出錯的情況下,數據序列化和傳輸的性能損耗也是問題。

  7. 【參考】避免出現重複的代碼(Don’t Repeat Yourself),即 DRY 原則。
    說明:隨意複製和粘貼代碼,必然會導致代碼的重複,在以後需要修改時,需要修改所有的副本,容易遺漏。必要時抽取共性方法,或者抽象公共類,甚至是組件化。
    正例:一個類中有多個 public 方法,都需要進行數行相同的參數校驗操作,這個時候請抽取:

private boolean checkParam(DTO dto) {...}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章