看了團隊中原來代碼中的異常處理,心碎了一地,稍微對照阿里巴巴的異常處理規範整理了一遍,準備分享一下,Java的異常處理規範&約束。程序員
不要捕獲 Java 類庫中定義的繼承自 RuntimeException 的運行時異常類,如:IndexOutOfBoundsException / NullPointerException ,這類異常由程序員預檢查來規避,保證程序健壯性。數據庫
正例:bash
if(null != obj) {
//TODO
}
複製代碼
反例:ui
try {
obj.method()
} catch(NullPointerException e){
//TODO
}
複製代碼
對大段代碼進行try-catch ,這是不負責任的表現。catch 時請分清穩定代碼和非穩定代碼,穩定代碼指的是不管如何不會出錯的代碼。對於非穩定代碼的 catch 儘量進行區分異常類型,再作對應的異常處理。url
正例: 分塊catch ,或者直接拋出相對應的異常,而後由下層細化處理。spa
map.put("status", 500);
try{
//代碼省略
map.put("message", "success!");
map.put("status", 200);
} catch (UnknownHostException e) {
//域名錯誤
map.put("message", "請輸入正確的網址");
LoggerUtils.fmtError(e, "網址異常[%s]", url);
} catch (SocketTimeoutException e) {
//超時
map.put("message", "請求地址超時");
LoggerUtils.fmtError(e, "請求地址超時[%s]", url);
} catch (Exception e) {
//其餘異常
map.put("message", "請求出現未知異常,請重試!\r\n" + e.getMessage());
LoggerUtils.fmtError(e, "請求出現未知異常,請重試![%s]", url);
}
return map;
複製代碼
反例:code
try {
//此處省略1024行代碼
} catch(Exception e){
//TODO
}
複製代碼
捕獲異常是爲了處理它,不要捕獲了卻什麼都不處理而拋棄之,若是不想處理它,請將該異常拋給它的調用者。最外層的業務使用者,必須處理異常,將其轉化爲用戶能夠理解的內容。cdn
正例:對象
try{
//代碼省略
} catch (UnknownHostException e) {
//域名錯誤
map.put("message", "請輸入正確的網址");
LoggerUtils.fmtError(XXXXManager.class, e, "網址異常[%s]", url);
} catch (SocketTimeoutException e) {
//超時
map.put("message", "請求地址超時");
LoggerUtils.fmtError(XXXXManager.class, e, "請求地址超時[%s]", url);
} catch (Exception e) {
//其餘異常
map.put("message", "請求出現未知異常,請重試!\r\n" + e.getMessage());
LoggerUtils.fmtError(XXXXManager.class, e, "請求出現未知異常,請重試![%s]", url);
}
複製代碼
只爲描述一下異常,繼續拋出。繼承
try{
//代碼省略
} catch (UnknownHostException e) {
throw new HNException("xxx處理失敗。",e);
}
複製代碼
反例: 1.以下,調用者對異常沒有任何感知。
try{
//代碼省略
} catch (Exception e) {
System.out.println("插入異常");
}
複製代碼
2.以下,調用者對異常沒法定位和判斷
try{
//代碼省略
} catch (UnknownHostException e) {
throw new RuntimeException("500");
}
複製代碼
1.若是有對IO 流和資源作操做,必須逐一關閉IO 流和資源對象(從裏層到外層),有異常也要作處理。
try{
//代碼省略
} catch (Exception e) {
throw new HNException("xxx處理失敗。",e);
}finally{
try {
if(null != conn){
conn.disconnect();
}
} catch (Exception e1) {
LoggerUtils.fmtInfo("請求完畢關閉流出現異常![%s]", url);
}
try {
if(null != outStream){
outStream.close();
}
} catch (Exception e2) {
LoggerUtils.fmtInfo("請求完畢關閉流出現異常![%s]", url);
}
try {
if(null != out){
out.close();
}
} catch (Exception e3) {
LoggerUtils.fmtInfo("請求完畢關閉流出現異常![%s]", url);
}
}
複製代碼
JDK 7 以上可使用try-with-resources 方式。
不能在 finally 塊中使用 return ,finally 塊中的 return 返回後方法結束執行,不會再執行 try 塊中的 return 語句。
捕獲異常與拋異常,必須是徹底匹配,或者捕獲異常是拋異常的父類。若是預期對方拋的是繡球,實際接到的是鉛球,就會產生意外狀況。
1.方法(接口)的返回值能夠爲 null ,但不推薦返回空集合,或者空對象等,必須添加註釋充分說明什麼狀況下會返回 null 值。調用方須要進行 null 判斷防止 NPE 問題。
防止 NPE ,是程序員的基本修養,注意 NPE 產生的場景。
a.查詢數據庫返回null ,包括null 對象和null 集合。
b.集合內元素有null 對象。