工作小驛

          Ninja!

          BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
            103 Posts :: 0 Stories :: 36 Comments :: 0 Trackbacks
          1. 異常機(jī)制

          1.1

          異常機(jī)制是指當(dāng)程序出現(xiàn)錯(cuò)誤后,程序如何處理。具體來(lái)說(shuō),異常機(jī)制提供了程序退出的安全通道。當(dāng)出現(xiàn)錯(cuò)誤后,程序執(zhí)行的流程發(fā)生改變,程序的控制權(quán)轉(zhuǎn)移到異常處理器。

          1.2

          傳統(tǒng)的處理異常的辦法是,函數(shù)返回一個(gè)特殊的結(jié)果來(lái)表示出現(xiàn)異常(通常這個(gè)特殊結(jié)果是大家約定俗稱(chēng)的),調(diào)用該函數(shù)的程序負(fù)責(zé)檢查并分析函數(shù)返回的結(jié)果。這樣做有如下的弊端:例如函數(shù)返回-1代表出現(xiàn)異常,但是如果函數(shù)確實(shí)要返回-1這個(gè)正確的值時(shí)就會(huì)出現(xiàn)混淆;可讀性降低,將程序代碼與處理異常的代碼混爹在一起;由調(diào)用函數(shù)的程序來(lái)分析錯(cuò)誤,這就要求客戶(hù)程序員對(duì)庫(kù)函數(shù)有很深的了解。

          1.3 異常處理的流程

          1.3.1 遇到錯(cuò)誤,方法立即結(jié)束,并不返回一個(gè)值;同時(shí),拋出一個(gè)異常對(duì)象

          1.3.2 調(diào)用該方法的程序也不會(huì)繼續(xù)執(zhí)行下去,而是搜索一個(gè)可以處理該異常的異常處理器,并執(zhí)行其中的代碼


          2 異常的分類(lèi)

          2.1 異常的分類(lèi)

          2.1.1

          異常的繼承結(jié)構(gòu):基類(lèi)為T(mén)hrowable,Error和Exception繼承Throwable,RuntimeException和IOException等繼承Exception,具體的RuntimeException繼承RuntimeException。

          2.1.2

          Error和RuntimeException及其子類(lèi)成為未檢查異常(unchecked),其它異常成為已檢查異常(checked)。

          2.2 每個(gè)類(lèi)型的異常的特點(diǎn)

          2.2.1 Error體系

          Error類(lèi)體系描述了Java運(yùn)行系統(tǒng)中的內(nèi)部錯(cuò)誤以及資源耗盡的情形。應(yīng)用程序不應(yīng)該拋出這種類(lèi)型的對(duì)象(一般是由虛擬機(jī)拋出)。如果出現(xiàn)這種錯(cuò)誤,除了盡力使程序安全退出外,在其他方面是無(wú)能為力的。所以,在進(jìn)行程序設(shè)計(jì)時(shí),應(yīng)該更關(guān)注Exception體系。

          2.2.2 Exception體系

          Exception體系包括RuntimeException體系和其他非RuntimeException的體系

          2.2.2.1 RuntimeException

          RuntimeException體系包括錯(cuò)誤的類(lèi)型轉(zhuǎn)換、數(shù)組越界訪問(wèn)和試圖訪問(wèn)空指針等等。處理RuntimeException的原則是:如果出現(xiàn)RuntimeException,那么一定是程序員的錯(cuò)誤。例如,可以通過(guò)檢查數(shù)組下標(biāo)和數(shù)組邊界來(lái)避免數(shù)組越界訪問(wèn)異常。

          2.2.2.2 其他(IOException等等)

          這類(lèi)異常一般是外部錯(cuò)誤,例如試圖從文件尾后讀取數(shù)據(jù)等,這并不是程序本身的錯(cuò)誤,而是在應(yīng)用環(huán)境中出現(xiàn)的外部錯(cuò)誤。

          2.3 與C++異常分類(lèi)的不同

          2.3.1

          其實(shí),Java中RuntimeException這個(gè)類(lèi)名起的并不恰當(dāng),因?yàn)槿魏萎惓6际沁\(yùn)行時(shí)出現(xiàn)的。(在編譯時(shí)出現(xiàn)的錯(cuò)誤并不是異常,換句話(huà)說(shuō),異常就是為了解決程序運(yùn)行時(shí)出現(xiàn)的的錯(cuò)誤)。

          2.3.2

          C++中l(wèi)ogic_error與Java中的RuntimeException是等價(jià)的,而runtime_error與Java中非RuntimeException類(lèi)型的異常是等價(jià)的。

          3 異常的使用方法


          3.1 聲明方法拋出異常

          3.1.1 語(yǔ)法:throws(略)

          3.1.2 為什么要聲明方法拋出異常?

          方法是否拋出異常與方法返回值的類(lèi)型一樣重要。假設(shè)方法拋出異常確沒(méi)有聲明該方法將拋出異常,那么客戶(hù)程序員可以調(diào)用這個(gè)方法而且不用編寫(xiě)處理異常的代碼。那么,一旦出現(xiàn)異常,那么這個(gè)異常就沒(méi)有合適的異??刂破鱽?lái)解決。

          3.1.3 為什么拋出的異常一定是已檢查異常?

          RuntimeException與Error可以在任何代碼中產(chǎn)生,它們不需要由程序員顯示的拋出,一旦出現(xiàn)錯(cuò)誤,那么相應(yīng)的異常會(huì)被自動(dòng)拋出。而已檢查異常是由程序員拋出的,這分為兩種情況:客戶(hù)程序員調(diào)用會(huì)拋出異常的庫(kù)函數(shù)(庫(kù)函數(shù)的異常由庫(kù)程序員拋出);客戶(hù)程序員自己使用throw語(yǔ)句拋出異常。遇到Error,程序員一般是無(wú)能為力的;遇到RuntimeException,那么一定是程序存在邏輯錯(cuò)誤,要對(duì)程序進(jìn)行修改(相當(dāng)于調(diào)試的一種方法);只有已檢查異常才是程序員所關(guān)心的,程序應(yīng)該且僅應(yīng)該拋出或處理已檢查異常。

          3.1.4

          注意:覆蓋父類(lèi)某方法的子類(lèi)方法不能拋出比父類(lèi)方法更多的異常,所以,有時(shí)設(shè)計(jì)父類(lèi)的方法時(shí)會(huì)聲明拋出異常,但實(shí)際的實(shí)現(xiàn)方法的代碼卻并不拋出異常,這樣做的目的就是為了方便子類(lèi)方法覆蓋父類(lèi)方法時(shí)可以?huà)伋霎惓!?

          3.2 如何拋出異常

          3.2.1 語(yǔ)法:throw(略)

          3.2.2 拋出什么異常?

          對(duì)于一個(gè)異常對(duì)象,真正有用的信息時(shí)異常的對(duì)象類(lèi)型,而異常對(duì)象本身毫無(wú)意義。比如一個(gè)異常對(duì)象的類(lèi)型是ClassCastException,那么這個(gè)類(lèi)名就是唯一有用的信息。所以,在選擇拋出什么異常時(shí),最關(guān)鍵的就是選擇異常的類(lèi)名能夠明確說(shuō)明異常情況的類(lèi)。

          3.2.3

          異常對(duì)象通常有兩種構(gòu)造函數(shù):一種是無(wú)參數(shù)的構(gòu)造函數(shù);另一種是帶一個(gè)字符串的構(gòu)造函數(shù),這個(gè)字符串將作為這個(gè)異常對(duì)象除了類(lèi)型名以外的額外說(shuō)明。

          3.2.4

          創(chuàng)建自己的異常:當(dāng)Java內(nèi)置的異常都不能明確的說(shuō)明異常情況的時(shí)候,需要?jiǎng)?chuàng)建自己的異常。需要注意的是,唯一有用的就是類(lèi)型名這個(gè)信息,所以不要在異常類(lèi)的設(shè)計(jì)上花費(fèi)精力。

          3.3 捕獲異常

          如果一個(gè)異常沒(méi)有被處理,那么,對(duì)于一個(gè)非圖形界面的程序而言,該程序會(huì)被中止并輸出異常信息;對(duì)于一個(gè)圖形界面程序,也會(huì)輸出異常的信息,但是程序并不中止,而是返回用Ы緱媧硌分小?BR> 3.3.1 語(yǔ)法:try、catch和finally(略)

          控制器模塊必須緊接在try塊后面。若擲出一個(gè)異常,異??刂茩C(jī)制會(huì)搜尋參數(shù)與異常類(lèi)型相符的第一個(gè)控制器隨后它會(huì)進(jìn)入那個(gè)catch

          從句,并認(rèn)為異常已得到控制。一旦catch 從句結(jié)束對(duì)控制器的搜索也會(huì)停止。

          3.3.1.1 捕獲多個(gè)異常(注意語(yǔ)法與捕獲的順序)(略)

          3.3.1.2 finally的用法與異常處理流程(略)

          3.3.2 異常處理做什么?

          對(duì)于Java來(lái)說(shuō),由于有了垃圾收集,所以異常處理并不需要回收內(nèi)存。但是依然有一些資源需要程序員來(lái)收集,比如文件、網(wǎng)絡(luò)連接和圖片等資源。

          3.3.3 應(yīng)該聲明方法拋出異常還是在方法中捕獲異常?

          原則:捕捉并處理哪些知道如何處理的異常,而傳遞哪些不知道如何處理的異常

          3.3.4 再次拋出異常

          3.3.4.1 為什么要再次拋出異常?

          在本級(jí)中,只能處理一部分內(nèi)容,有些處理需要在更高一級(jí)的環(huán)境中完成,所以應(yīng)該再次拋出異常。這樣可以使每級(jí)的異常處理器處理它能夠處理的異常。

          3.3.4.2 異常處理流程

          對(duì)應(yīng)與同一try塊的catch塊將被忽略,拋出的異常將進(jìn)入更高的一級(jí)。

          4 關(guān)于異常的其他問(wèn)題

          4.1 過(guò)度使用異常

          首先,使用異常很方便,所以程序員一般不再愿意編寫(xiě)處理錯(cuò)誤的代碼,而僅僅是簡(jiǎn)簡(jiǎn)單單的拋出一個(gè)異常。這樣做是不對(duì)的,對(duì)于完全已知的錯(cuò)誤,應(yīng)該編寫(xiě)處理這種錯(cuò)誤的代碼,增加程序的魯棒性。另外,異常機(jī)制的效率很差。

          4.2 將異常與普通錯(cuò)誤區(qū)分開(kāi)

          對(duì)于普通的完全一致的錯(cuò)誤,應(yīng)該編寫(xiě)處理這種錯(cuò)誤的代碼,增加程序的魯棒性。只有外部的不能確定和預(yù)知的運(yùn)行時(shí)錯(cuò)誤才需要使用異常。

          4.3 異常對(duì)象中包含的信息

          一般情況下,異常對(duì)象唯一有用的信息就是類(lèi)型信息。但使用異常帶字符串的構(gòu)造函數(shù)時(shí),這個(gè)字符串還可以作為額外的信息。調(diào)用異常對(duì)象的getMessage()、toString()或者printStackTrace()方法可以分別得到異常對(duì)象的額外信息、類(lèi)名和調(diào)用堆棧的信息。并且后一種包含的信息是前一種的超集
          posted on 2007-09-20 15:55 王君 閱讀(1183) 評(píng)論(1)  編輯  收藏 所屬分類(lèi): J2SE

          Feedback

          # re: Java異常處理機(jī)制的詳細(xì)講解和使用技巧 2007-09-27 19:30 千里冰封
          異常機(jī)制也須好好掌握  回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 巴彦淖尔市| 深泽县| 德昌县| 贵州省| 永吉县| 西畴县| 麦盖提县| 桃园市| 日土县| 丹江口市| 旬阳县| 商丘市| 梁山县| 温州市| 怀柔区| 鄂伦春自治旗| 东明县| 临漳县| 昌黎县| 团风县| 卓资县| 双桥区| 拜城县| 新泰市| 马尔康县| 蒙城县| 裕民县| 阿坝| 灯塔市| 芜湖县| 苗栗县| 石柱| 沽源县| 新河县| 东宁县| 齐齐哈尔市| 鄂州市| 汝南县| 临邑县| 芮城县| 黄浦区|