1. 程式人生 > >Java 異常處理基本規則,Java異常處理的基本規範

Java 異常處理基本規則,Java異常處理的基本規範

看了團隊中原來程式碼中的異常處理,心碎了一地,稍微對照阿里巴巴的異常處理規範整理了一遍,準備分享一下,Java的異常處理規範&約束。

一、執行異常的撲捉

不要捕獲   Java  類庫中定義的繼承自 RuntimeException 的執行時異常類,如:IndexOutOfBoundsException / NullPointerException ,這類異常由程式設計師預檢查來規避,保證程式健壯性。

正例:

 

  1. if(null != obj) {

  2.    //TODO

  3. }

 

反例:

 

  1. try {

  2.    obj.method()

  3. } catch(NullPointerException e){

  4.   //TODO

  5. }

 

二、 try-catch 作用域(現有程式碼出現率較高)

對大段程式碼進行try-catch ,這是不負責任的表現。catch 時請分清穩定程式碼和非穩定程式碼,穩定程式碼指的是無論如何不會出錯的程式碼。對於非穩定程式碼的 catch 儘可能進行區分異常型別,再做對應的異常處理。
正例:


分塊catch ,或者直接丟擲相對應的異常,然後由下層細化處理。

 

  1. map.put("status", 500);  

  2. try{

  3.    //程式碼省略

  4.    map.put("message", "success!");  

  5.    map.put("status", 200);  

  6. } catch (UnknownHostException e) {

  7.    //域名錯誤

  8.    map.put("message", "請輸入正確的網址");

  9.    LoggerUtils.fmtError(e, "網址異常[%s]", url);

  10. } catch (SocketTimeoutException e) {

  11.    //超時

  12.    map.put("message", "請求地址超時");

  13.    LoggerUtils.fmtError(e, "請求地址超時[%s]", url);

  14.  

  15. } catch (Exception e) {

  16.    //其他異常

  17.    map.put("message", "請求出現未知異常,請重試!\r\n" + e.getMessage());

  18.    LoggerUtils.fmtError(e, "請求出現未知異常,請重試![%s]", url);

  19. }

  20. return map;

 

反例: 

 

  1. try {

  2.   //此處省略1024行程式碼

  3. } catch(Exception e){

  4.   //TODO

  5. }

 

三、異常的捕捉 & 異常的處理(現有程式碼出現率較高)

捕獲異常是為了處理它,不要捕獲了卻什麼都不處理而拋棄之,如果不想處理它,請將該異常拋給它的呼叫者。最外層的業務使用者,必須處理異常,將其轉化為使用者可以理解的內容。

正例:

 

  1. try{

  2.    //程式碼省略

  3. } catch (UnknownHostException e) {

  4.    //域名錯誤

  5.    map.put("message", "請輸入正確的網址");

  6.    LoggerUtils.fmtError(XXXXManager.class, e, "網址異常[%s]", url);

  7. } catch (SocketTimeoutException e) {

  8.    //超時

  9.    map.put("message", "請求地址超時");

  10.    LoggerUtils.fmtError(XXXXManager.class, e, "請求地址超時[%s]", url);

  11.  

  12. } catch (Exception e) {

  13.    //其他異常

  14.    map.put("message", "請求出現未知異常,請重試!\r\n" + e.getMessage());

  15.    LoggerUtils.fmtError(XXXXManager.class, e, "請求出現未知異常,請重試![%s]", url);

  16. }

 

只為描述一下異常,繼續丟擲。 

 

  1. try{

  2.    //程式碼省略

  3. } catch (UnknownHostException e) {

  4.    throw new HNException("xxx處理失敗。",e);

  5. }

 

反例:

1.如下,呼叫者對異常沒有任何感知。 

 

  1. try{

  2.    //程式碼省略

  3. } catch (Exception e) {

  4.    System.out.println("插入異常");

  5. }

 

2.如下,呼叫者對異常無法定位和判斷 

 

  1. try{

  2.    //程式碼省略

  3. } catch (UnknownHostException e) {

  4.    throw new RuntimeException("500");

  5. }

 

四、異常 & 事務

  1. 有 try 塊放到了事務程式碼中,catch 異常後,如果需要回滾事務,一定要注意手動回滾事務。

  2. 在有事務的程式碼中,catch 異常後,做描述異常等處理後,如果需要事務生效,請把異常繼續丟擲。

五、異常 & finally

1.如果有對IO 流和資源做操作,必須逐一關閉IO 流和資源物件(從裡層到外層),有異常也要做處理。

 

try{

  1.    //程式碼省略

  2. } catch (Exception e) {

  3.    throw new HNException("xxx處理失敗。",e);

  4.  

  5. }finally{

  6.            

  7.    try {

  8.        if(null != conn){

  9.            conn.disconnect();

  10.        }

  11.    } catch (Exception e1) {

  12.        LoggerUtils.fmtInfo("請求完畢關閉流出現異常![%s]", url);

  13.    }

  14.    try {

  15.        if(null != outStream){

  16.            outStream.close();

  17.        }

  18.    } catch (Exception e2) {

  19.        LoggerUtils.fmtInfo("請求完畢關閉流出現異常![%s]", url);

  20.    }

  21.    try {

  22.        if(null != out){

  23.            out.close();

  24.        }

  25.    } catch (Exception e3) {

  26.        LoggerUtils.fmtInfo("請求完畢關閉流出現異常![%s]", url);

  27.    }

  28.            

  29. }

 

  JDK  7 以上可以使用try-with-resources 方式。 

六、finally &  return

不能在 finally 塊中使用 return ,finally 塊中的 return 返回後方法結束執行,不會再執行 try 塊中的 return 語句。 

七、異常需要精確

捕獲異常與拋異常,必須是完全匹配,或者捕獲異常是拋異常的父類。如果預期對方拋的是繡球,實際接到的是鉛球,就會產生意外情況。

八、程式設計師的基本修養 & NPE(現有程式碼中出現率較高)

1.方法(介面)的返回值可以為 null ,但不推薦返回空集合,或者空物件等,必須添加註釋充分說明什麼情況下會返回 null 值。呼叫方需要進行 null 判斷防止 NPE 問題。

2. 防止 NPE ,是程式設計師的基本修養,注意 NPE 產生的場景。

    a.查詢資料庫返回null ,包括null 物件和null 集合。

    b.集合內元素有null 物件。