Java異常處理的原則和忌諱
2010-11-05 13:51:10 來源:網(wǎng)絡 評論: 點擊:35
Java 異常處理的原則
Java 異常處理的原則
盡可能的處理異常
要盡可能的處理異常,如果條件確實不允許,無法在自己的代碼中完成處理,就考慮聲明異常。如果人為避免在代碼中處理異常,僅作聲明,則是一種錯誤和依賴的實踐。
具體問題具體解決
異常的部分優(yōu)點在于能為不同類型的問題提供不同的處理操作。有效異常處理的關(guān)鍵是識別特定故障場景,并開發(fā)解決此場景的特定相應行為。為了充分利用異常處理能力,需要為特定類型的問題構(gòu)建特定的處理器塊。
記錄可能影響應用程序運行的異常
至少要采取一些永久的方式,記錄下可能影響應用程序操作的異常。理想情況下,當然是在第一時間解決引發(fā)異常的基本問題。不過,無論采用哪種處理操作,一般總應記錄下潛在的關(guān)鍵問題。別看這個操作很簡單,但它可以幫助您用很少的時間來跟蹤應用程序中復雜問題的起因。
根據(jù)情形將異常轉(zhuǎn)化為業(yè)務上下文
若要通知一個應用程序特有的問題,有必要將應用程序轉(zhuǎn)換為不同形式。若用業(yè)務特定狀態(tài)表示異常,則代碼更易維護。從某種意義上講,無論何時將異常傳到不同上下文(即另一技術(shù)層),都應將異常轉(zhuǎn)換為對新上下文有意義的形式。
Java 異常處理的忌諱
一般不要忽略異常
在異常處理塊中,一項最危險的舉動是“不加通告”地處理異常。如下例所示:
try{
Class.forName("business.domain.Customer");
}
catch (ClassNotFoundException exc){}
經(jīng)常能夠在代碼塊中看到類似的代碼塊。有人總喜歡在編寫代碼時簡單快速地編寫空處理器塊,并“自我安慰地”宣稱準備在“后期”添加恢復代碼,但這個“后期”變成了“無期”。
這種做法有什么壞處?如果異常對應用程序的其他部分確實沒有任何負面影響,這未嘗不可。但事實往往并非如此,異常會擾亂應用程序的狀態(tài)。此時,這樣的代碼無異于掩耳盜鈴。
這種做法若影響較輕,則應用程序可能出現(xiàn)怪異行為。例如,應用程序設置的一個值不見了, 或 GUI 失效。若問題嚴重,則應用程序可能會出現(xiàn)重大問題,因為異常未記錄原始故障點,難以處理,如重復的 NullPointerExceptions。
如果采取措施,記錄了捕獲的異常,則不可能遇到這個問題。實際上,除非確認異常對代碼其余部分絕無影響,至少也要作記錄。進一步講,永遠不要忽略問題;否則,風險很大,在后期會引發(fā)難以預料的后果。
不要使用覆蓋式異常處理塊
另一個危險的處理是覆蓋式處理器(blanket handler)。該代碼的基本結(jié)構(gòu)如下:
try{
// …
}
catch(Exception e){
// …
}
使用覆蓋式異常處理塊有兩個前提之一:
1. 代碼中只有一類問題。
這可能正確,但即便如此,也不應使用覆蓋式異常處理,捕獲更具體的異常形式有利物弊。
2. 單個恢復操作始終適用。
這幾乎絕對錯誤。幾乎沒有哪個方法能放之四海而皆準,能應對出現(xiàn)的任何問題。
分析下這樣編寫代碼將發(fā)生的情況。只要方法不斷拋出預期的異常集,則一切正常。但是,如果拋出了未預料到的異常,則無法看到要采取的操作。當覆蓋式處理器對新異常類執(zhí)行千篇一律的任務時,只能間接看到異常的處理結(jié)果。如果代碼沒有打印或記錄語句,則根本看不到結(jié)果。
更糟糕的是,當代碼發(fā)生變化時,覆蓋式處理器將繼續(xù)作用于所有新異常類型,并以相同方式處理所有類型。
一般不要把特定的異常轉(zhuǎn)化為更通用的異常
將特定的異常轉(zhuǎn)換為更通用異常時一種錯誤做法。一般而言,這將取消異常起初拋出時產(chǎn)生的上下文,在將異常傳到系統(tǒng)的其他位置時,將更難處理。見下例:
try{
// Error-prone code
}
catch(IOException e){
String msg = "If you didn ’ t have a problem before,you do now!";
throw new Exception(msg);
}
因為沒有原始異常的信息,所以處理器塊無法確定問題的起因,也不知道如何更正問題。
不要處理能夠避免的異常
對于有些異常類型,實際上根本不必處理。通常運行時異常屬于此類范疇。在處理空指針或者數(shù)據(jù)索引等問題時,不必求助于異常處理。
|