Java異常為我們提供了一致的識(shí)別和處理程序錯(cuò)誤的機(jī)制,有效的異常處理能增強(qiáng)程序的健壯性和易于調(diào)試性。

首先還是重溫下java的異常體系結(jié)構(gòu),如圖所示,所有異常的根是Throwable,異常又分為checked exceptionunchecked exceptionRuntimeException就是屬于unchecked exception,JVM 一旦捕捉到unchecked exception 就會(huì)終止當(dāng)前運(yùn)行的程序,并在console中打出錯(cuò)誤信息。

 

Java exception hierarchyption hierarchy

一、Unchecked exceptions VS Checked exceptions

 下表列出使用兩種異常的場(chǎng)合:

Client's reaction when exception happens

Exception type

Client code cannot do anything

Make it an unchecked exception

Client code will take some useful recovery action based on information in exception

Make it a checked exception

 這個(gè)方面的例子hibernate就是一個(gè),在hibernate2中,HibernateException還是checked exceptions,但是到了hibernate3中就成了unchecked exceptions,因?yàn)閷?duì)于數(shù)據(jù)庫(kù)操作來(lái)說(shuō),一旦出現(xiàn)異常,就是比較嚴(yán)重的錯(cuò)誤,而且在client端基本上是無(wú)能為力的,使用unchecked exceptions更加合適。

另外,unchecked exceptions的優(yōu)點(diǎn)在于不強(qiáng)迫客戶端代碼顯式地處理他們,異??梢砸恢蓖蟼鬟f(除非需要轉(zhuǎn)化異常,否則異常不需要在中間被捕捉,節(jié)省了很多的try{}catch(),代碼更加簡(jiǎn)潔),直到你想捕捉處理他們,(有人會(huì)問(wèn),如何不強(qiáng)制客戶端處理他們,比如像checked exceptions這樣,不處理就是語(yǔ)法錯(cuò)誤,如何保證異常能夠得到處理呢?在這點(diǎn)上,java提供的完善的文檔機(jī)制,通過(guò)API客戶端程序員可以很方便地知道他調(diào)用的方法可能會(huì)拋出什么異常,一個(gè)負(fù)責(zé)人的程序員就應(yīng)該對(duì)其進(jìn)行catch和處理),Java API提供了很多的unchecked exceptions,比如NullPointerException, IllegalArgumentException, and IllegalStateException,使用java提供的標(biāo)準(zhǔn)的unchecked exceptions是值得推薦的,這樣的好處在于使代碼更加簡(jiǎn)潔并可以減少代碼對(duì)內(nèi)存的占用。

二、Java異常的推遲處理

Java異常應(yīng)該盡可能地推遲處理,除非要轉(zhuǎn)化異常,重新拋出,否則最好不要處理,而是留給最后能夠處理異常的地方。

通過(guò)為方法添加throws聲明,可以將處理異常的責(zé)任傳遞到更高的層次。在聲明哪些需要拋出的時(shí)候,應(yīng)該盡可能地詳細(xì)。這樣做的目的是可以在API中詳細(xì)地表述出該方法可能會(huì)出現(xiàn)的異常,從而讓調(diào)用該方法的clinet程序員做好處理異常的準(zhǔn)備,比如對(duì)于代碼通過(guò)throws語(yǔ)句詳細(xì)地聲明了可能會(huì)拋出的異常,這樣調(diào)用該方法的程序員就會(huì)知道將會(huì)有什么樣的異常會(huì)發(fā)生。

public void readPreferences(String filename)

    
throws IllegalArgumentException,

          FileNotFoundException, IOException
{

    
if (filename == null)
    {

        
throw new IllegalArgumentException

                        (
"filename is null");

    }  
//if
    
//
    InputStream in = new FileInputStream(filename);

    
//
}

從語(yǔ)法上講,IllegalArgumentExceptionunckecked exception 是不需要聲明的,但是為了從文檔的角度考慮,最好還是加上,這樣可以讓調(diào)用這個(gè)方法的程序員知道,這個(gè)方法會(huì)可能拋出該異常,需要加以捕捉和處理。

 

三、異常的處理

不管如何,最終程序肯定是要對(duì)異常進(jìn)行處理的,否則會(huì)導(dǎo)致不確定情況的發(fā)生,但是選擇異常處理的位置卻是有技巧的,通常要么是程序在這些地方從異常中恢復(fù)、繼續(xù)執(zhí)行且不會(huì)導(dǎo)致進(jìn)一步異常的發(fā)生,要么是在這些地方能為用戶反饋特定的信息,比如,如何避免異常的發(fā)生或者如何從異常中恢復(fù)。因此,對(duì)于有用戶界面層的程序,將異常的捕捉和處理推遲到UI層是有好處的,在UI層可以使用對(duì)話框或者其他方式提示用戶出現(xiàn)異常。
 

參考文獻(xiàn)

Best Practices for Exception Handling by Gunjan Doshi

Three Rules for Effective Exception Handling by Jim Cushing