畢業(yè)設(shè)計(jì)-基于java的異常處理技術(shù)及其應(yīng)用_第1頁
畢業(yè)設(shè)計(jì)-基于java的異常處理技術(shù)及其應(yīng)用_第2頁
畢業(yè)設(shè)計(jì)-基于java的異常處理技術(shù)及其應(yīng)用_第3頁
畢業(yè)設(shè)計(jì)-基于java的異常處理技術(shù)及其應(yīng)用_第4頁
畢業(yè)設(shè)計(jì)-基于java的異常處理技術(shù)及其應(yīng)用_第5頁
已閱讀5頁,還剩22頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

1、目 錄 TOC o 1-3 h z u HYPERLINK l _Toc105574582 一 引言 PAGEREF _Toc105574582 h 1 HYPERLINK l _Toc105574583 二 關(guān)于JDK和Java異常 PAGEREF _Toc105574583 h 2 HYPERLINK l _Toc105574584 一Java異常定義 PAGEREF _Toc105574584 h 2 HYPERLINK l _Toc105574585 二Java中的異常類 PAGEREF _Toc105574585 h 2 HYPERLINK l _Toc105574586 三Java

2、語言標(biāo)準(zhǔn)對(duì)異常處理的要求 PAGEREF _Toc105574586 h 4 HYPERLINK l _Toc105574587 三 Java異常的處理機(jī)制 PAGEREF _Toc105574587 h 4 HYPERLINK l _Toc105574588 一Java異常處理機(jī)制具體實(shí)現(xiàn) PAGEREF _Toc105574588 h 4 HYPERLINK l _Toc105574589 二Java中異常發(fā)生的原因 PAGEREF _Toc105574589 h 6 HYPERLINK l _Toc105574590 三Java異常處理的優(yōu)點(diǎn) PAGEREF _Toc105574590

3、h 6 HYPERLINK l _Toc105574591 四 Java異常處理技術(shù)及其應(yīng)用 PAGEREF _Toc105574591 h 8 HYPERLINK l _Toc105574592 一拋出異常 PAGEREF _Toc105574592 h 8 HYPERLINK l _Toc105574593 二捕獲異常 PAGEREF _Toc105574593 h 8 HYPERLINK l _Toc105574594 三堆棧幀 PAGEREF _Toc105574594 h 9 HYPERLINK l _Toc105574595 四自定義異常 PAGEREF _Toc105574595

4、 h 11 HYPERLINK l _Toc105574596 五關(guān)于圖形界面程序的異常捕獲 PAGEREF _Toc105574596 h 12 HYPERLINK l _Toc105574597 五 Java異常處理根本原那么 PAGEREF _Toc105574597 h 14 HYPERLINK l _Toc105574598 (一)不要忽略已檢查型異常 PAGEREF _Toc105574598 h 14 HYPERLINK l _Toc105574599 (二)不要一次捕獲所有的異常 PAGEREF _Toc105574599 h 15 HYPERLINK l _Toc105574

5、600 (三)使用finally塊釋放資源 PAGEREF _Toc105574600 h 16 HYPERLINK l _Toc105574601 (四)異常不能影響對(duì)象的狀態(tài) PAGEREF _Toc105574601 h 17 HYPERLINK l _Toc105574602 (五)注意喪失或忽略的異常 PAGEREF _Toc105574602 h 17 HYPERLINK l _Toc105574603 (六)不要同時(shí)使用異常機(jī)制和返回值來處理異常 PAGEREF _Toc105574603 h 20 HYPERLINK l _Toc105574604 (七)不要讓try塊過于龐大

6、 PAGEREF _Toc105574604 h 21 HYPERLINK l _Toc105574605 六 結(jié)束語 PAGEREF _Toc105574605 h 21 HYPERLINK l _Toc105574606 致謝 PAGEREF _Toc105574606 h 21 HYPERLINK l _Toc105574607 參考文獻(xiàn) PAGEREF _Toc105574607 h 22 HYPERLINK l _Toc105574608 附錄、源代碼 PAGEREF _Toc105574608 h 22基于Java的異常處理技術(shù)及其應(yīng)用摘 要 本文以Java軟件開發(fā)工具箱作為環(huán)境,

7、通過與一些編程語言的錯(cuò)誤處理相比擬,介紹了Java中異常處理技術(shù)的由來、定義、標(biāo)準(zhǔn)和Java內(nèi)建的異常類,討論了Java中異常產(chǎn)生的原因、實(shí)現(xiàn),還對(duì)Java異常處理機(jī)制的優(yōu)點(diǎn)進(jìn)行了簡述,就Java異常處理技術(shù)從拋出異常、捕獲異常、堆棧幀、自定義異常、圖形界面程序異常捕獲五個(gè)方面進(jìn)行了討論。本文還就Java異常處理技術(shù)的應(yīng)用做了一些探討,試圖從軟件開發(fā)者的角度說明Java異常處理技術(shù)在開發(fā)中一些有價(jià)值的應(yīng)用。關(guān)鍵詞 Java語言 Java異常處理 JVM 一 引言在程序設(shè)計(jì)中,盡管編寫檢查和處理錯(cuò)誤的程序代碼很乏味,并且它們使程序源代碼顯得冗長,但是,錯(cuò)誤檢測和處理仍是任何健壯應(yīng)用程序最重要的組

8、成局部之一。傳統(tǒng)的異常處理多采用返回值來標(biāo)識(shí)程序中出現(xiàn)的異常情況,這是程序員熟悉的一種方式,但卻有很多缺點(diǎn)。首先,一個(gè)APIApplication Programming Interface 應(yīng)用編程接口可以返回任意的返回值,而這些返回值本身并不能解釋是否代表一個(gè)異常情況發(fā)生或者發(fā)生異常的具體情況,需要調(diào)用API的程序自己判斷并解釋返回值的含義。其次,它并沒有一種機(jī)制來保證異常情況一定會(huì)得到處理,調(diào)用程序可以簡單地忽略該返回值,從而需要調(diào)用API的程序員記住去檢測返回值并處理異常情況。這種方式還讓程序代碼變得晦澀冗長, 當(dāng)進(jìn)行容易出現(xiàn)異常情況的處理時(shí),比方:I/O操作,程序中會(huì)出現(xiàn)很大的局部用

9、于處理異常情況的switch分支,程序代碼的可讀性變得很差。相對(duì)于傳統(tǒng)異常處理方式的缺點(diǎn),Java異常處理機(jī)制提供了很好的解決方案。Java異常處理使開發(fā)人員不用編寫特殊代碼檢測返回值就能夠很容易地檢測錯(cuò)誤,并且把異常處理代碼和異常產(chǎn)生代碼明確地分開,通過拋出Java預(yù)定義或者自定義的異常,能夠說明程序中出現(xiàn)了什么樣的異常情況1;而且Java的語言機(jī)制保證了異常一定會(huì)得到恰當(dāng)?shù)奶幚恚侠淼厥褂卯惓L幚頇C(jī)制,會(huì)讓程序代碼更清晰。 二 關(guān)于JDK和Java異常一Java異常定義 早期的編程語言比方C語言沒有異常處理,通常是遇到錯(cuò)誤返回一個(gè)特殊的值或設(shè)定一個(gè)標(biāo)志,并以此判斷是不是有錯(cuò)誤產(chǎn)生。隨著系統(tǒng)

10、規(guī)模的不斷擴(kuò)大,這種錯(cuò)誤處理已經(jīng)成為創(chuàng)立大型可維護(hù)程序的障礙了。于是在一些語言中出現(xiàn)了異常處理機(jī)制,比方在Basic中的異常處理語句“on error goto,而Java那么是在C+根底上建立了新的異常處理機(jī)制。Java通過面向?qū)ο蟮姆椒ㄟM(jìn)行異常處理,把各種不同的異常進(jìn)行分類,并提供了良好的接口。這種機(jī)制為復(fù)雜程序提供了強(qiáng)有力的控制方式。同時(shí)這些異常代碼與“常規(guī)代碼別離,增強(qiáng)了程序的可讀性,編寫程序時(shí)也顯得更靈活。 在編譯時(shí)沒有問題的Java源程序,在運(yùn)行期可能還會(huì)發(fā)生錯(cuò)誤,這種錯(cuò)誤就稱為異常Exception。異常也可認(rèn)為是程序運(yùn)行過程中違背正常指令流而產(chǎn)生的事件2。二Java中的異常類在

11、Java中,所有的異常都是以類對(duì)象的形式存在的。每個(gè)異常都是Throwable類或其子類的實(shí)例。當(dāng)一個(gè)方法出現(xiàn)異常后便拋出一個(gè)異常對(duì)象,該對(duì)象中包含有異常信息,調(diào)用這個(gè)對(duì)象的方法可以捕獲到這個(gè)異常并進(jìn)行處理3。Throwable是所有異常的基類,程序中一般不會(huì)直接拋出Throwable對(duì)象,Exception和Error是Throwable的子類,Exception下面又有RuntimeException和一般的Exception兩類??梢园袹ava異常分為三類:第一類是Error,Error表示程序在運(yùn)行期間出現(xiàn)了十分嚴(yán)重、不可恢復(fù)的錯(cuò)誤,在這種情況下應(yīng)用程序只能終止運(yùn)行,例如Java虛擬機(jī)

12、JVM出現(xiàn)錯(cuò)誤。在EJBEnterprise JavaBean中將此類歸為JVM 異常,這種類型的異常由 JVM 拋出。Error是一種uncheckedException未檢查型異常,編譯器不會(huì)檢查Error是否被處理,在程序中不用捕獲Error類型的異常;一般情況下,在程序中也不應(yīng)該拋出Error類型的異常。第二類是RuntimeException,在EJB也稱為系統(tǒng)異常。RuntimeException是一種未檢查型異常,即表示編譯器不會(huì)檢查程序是否對(duì)RuntimeException作了處理,在程序中不必捕獲未檢查型異常,也不必在方法體聲明拋出RuntimeException類。Runt

13、imeException發(fā)生的時(shí)候,表示程序中出現(xiàn)了編程錯(cuò)誤,所以應(yīng)該找出錯(cuò)誤修改程序,而不是去捕獲RuntimeException。ThrowableErrorExceptionRuntimeExceptionIOException 圖21 Java異常類層次圖第三類是一般的checkedException, 即已檢查型異常。在EJB中稱為應(yīng)用程序異常。已檢查型異常是在編程中使用最多的異常,所有繼承自Exception并且不是RuntimeException的異常都是已檢查型異常,如圖2-1中為Java異常的類層次圖。都聲明有標(biāo)準(zhǔn)異常類。這些異常類以未檢查型異常類和已檢查型異常類可分為如下:

14、已檢查型異常類主要有:1在java.lang中:ClassNotFoundException:指定名字的類或接口沒有被發(fā)現(xiàn)。CloneNotSupportedException:克隆一個(gè)沒有實(shí)現(xiàn)Cloneable接口的類。IllegalAccessException:試圖使用給出了完全路徑信息的字符串加載一個(gè)類,但當(dāng)前正在執(zhí)行的方法無法訪問指定的類,原因是該類不是public類或是在另一個(gè)包中。InstantiationException:試圖使用Class的newInstance方法創(chuàng)立一個(gè)對(duì)象實(shí)例,但是,指定的對(duì)象沒有被實(shí)例化,因?yàn)樗且粋€(gè)接口、抽象類或者一個(gè)數(shù)組。InterruptedE

15、xception:當(dāng)前的線程正在等待,而另一個(gè)線程那么使用了Thread的interrupt方法中斷了當(dāng)前線程。2在Java.io中:IOException:申請(qǐng)I/O操作沒有成功。EOFException:在輸入操作正常結(jié)束前遇到了文件結(jié)束符。FileNotFoundException:在文件系統(tǒng)中,沒有找到由文件名字符串指定的文件。InterruptedIOException當(dāng)前線程正在等待I/O操作的完成,而另一個(gè)線程使用thread的interrupt方法中斷了當(dāng)前線程。未檢查型異常類主要有:1在java.lang中:ArithmeticException:表示遇到了算術(shù)的異常問題,例

16、如0作為除數(shù)。ArrayStoreException:試圖把與數(shù)組類型不相符的值存入數(shù)組。ClassCastException:試圖把一個(gè)對(duì)象的引用強(qiáng)制轉(zhuǎn)換為不適宜的類型。InderOutOfBoundsException:數(shù)組的下標(biāo)越界。NullPointerException:試圖使用一個(gè)空的對(duì)象引用。SecurityException:檢測到了違反平安的行為。2在java.util中:EmptyStaceException:試圖訪問一個(gè)空堆棧中的一個(gè)元素。NoSuchElementException:試圖訪問一個(gè)空向量中的元素。三Java語言標(biāo)準(zhǔn)對(duì)異常處理的要求Java語言規(guī)定必須對(duì)已檢

17、查型異常作處理,編譯器會(huì)對(duì)此作檢查,要么在方法體中聲明拋出已檢查型異常,要么使用catch語句捕獲已檢查型異常進(jìn)行處理,不然不能通過編譯2。已檢查型異常用于以下環(huán)境:1)該異常發(fā)生后是可以被恢復(fù)的,如一個(gè)Internet連接發(fā)生異常被終止后,可以重新連接再進(jìn)行后續(xù)操作。2)程序依賴于不可靠的外部條件,該依賴條件可能出錯(cuò),如系統(tǒng)I/O。3)該異常發(fā)生后并不會(huì)導(dǎo)致程序處理錯(cuò)誤,進(jìn)行一些處理后可以繼續(xù)后續(xù)操作。Java語言標(biāo)準(zhǔn)中將任何Error的子類以及RuntimeException的子類都稱為未檢查型異常。而其它異常都稱為已檢查型異常。三 Java異常的處理機(jī)制一Java異常處理機(jī)制具體實(shí)現(xiàn)在J

18、ava程序運(yùn)行出現(xiàn)異常時(shí),發(fā)生異常的程序段要拋出異常,而運(yùn)行系統(tǒng)負(fù)責(zé)尋找一段代碼來處理異常。Java語言中,創(chuàng)立一個(gè)異常對(duì)象并將它交給運(yùn)行系統(tǒng)稱為拋出一個(gè)異常,又稱為異常拋出。在Java中,一個(gè)方法要拋出異常,必須遵循一定的規(guī)定,即所謂的“異常標(biāo)準(zhǔn)。異常標(biāo)準(zhǔn)采用了一個(gè)額外的關(guān)鍵字:throws。要使方法拋出異常,應(yīng)在方法聲明中,位于參變量列表的后面即throws后面列舉全部潛在的異常類型。假假設(shè)Java中的某方法可能拋出一個(gè)異常,但程序中沒有對(duì)其進(jìn)行控制,編譯器會(huì)偵測到這個(gè)情況,通知程序員必須在此方法內(nèi)進(jìn)行異常控制,或者從方法里拋出一個(gè)異常。通過遵守異常標(biāo)準(zhǔn),Java可在編譯期保證異常處理的正

19、確性。當(dāng)Java拋出一個(gè)異常,程序?qū)膶?dǎo)致異常的代碼處跳出,JVM檢測尋找和try關(guān)鍵字匹配的處理該異常的catch塊,如果找到,將控制權(quán)交到catch塊中的代碼,然后繼續(xù)往下執(zhí)行程序, 如果沒有找到處理該異常的catch塊,try塊中發(fā)生異常的代碼不會(huì)被重新執(zhí)行,在所有的finally塊代碼被執(zhí)行和當(dāng)前線程的所屬的ThreadGroup的uncaughtException方法被調(diào)用后,遇到異常的當(dāng)前線程被終止。Java異常處理的語句形式如下:try/正常執(zhí)行的代碼可能產(chǎn)生異常throw(異常類1 e,異常類2 e,異常類n e)catch(異常類1 e)/異常類1的處理代碼catch(異常類

20、2 e)/異常類2的處理代碼catch(異常類n e)/異常類n的處理代碼finally/執(zhí)行去除工作的語句Java程序運(yùn)行在try塊中,如果產(chǎn)生了異常,那么不再運(yùn)行try塊下面的語句,而直接進(jìn)入catch塊中,尋找第一個(gè)與之匹配的異常類型。try/catch語句會(huì)自動(dòng)在try塊后面的各個(gè)catch塊中,找出與該異常類相匹配的參數(shù)。如果該參數(shù)符合以下三個(gè)條件之一時(shí),那么認(rèn)為這個(gè)參數(shù)與產(chǎn)生的異常相匹配4。(1)參數(shù)與產(chǎn)生的異常屬于同一個(gè)類。(2)參數(shù)是產(chǎn)生異常的父類。(3)參數(shù)是一個(gè)接口,產(chǎn)生的異常實(shí)現(xiàn)了這一個(gè)接口。當(dāng)產(chǎn)生的異常找到了第一個(gè)與之相匹配的參數(shù)時(shí),就執(zhí)行這一參數(shù)的catch塊中的Ja

21、va代碼。執(zhí)行完catch塊后,程序恢復(fù)執(zhí)行,但不會(huì)回到異常發(fā)生處繼續(xù)執(zhí)行而是執(zhí)行try/catch結(jié)構(gòu)后面的代碼。finally語句可以說是為異常處理事件提供的一個(gè)清理機(jī)構(gòu)。一般是用來關(guān)閉文件或者釋放其他的系統(tǒng)資源作為try/catch/finally結(jié)構(gòu)的一局部,可以沒有finally塊。如果存在finally塊,無論try塊中是否發(fā)生異常,是否執(zhí)行過catch塊,都要執(zhí)行finally塊。用finally塊的一個(gè)好處,就是把方法中所有去除狀態(tài)和關(guān)閉系統(tǒng)文件的語句放在一起,不但防止代碼的重復(fù),更是減少出現(xiàn)遺漏語句,對(duì)于程序以后的修改也較為集中和方便。二Java中異常發(fā)生的原因異常發(fā)生有三種

22、原因:1Java虛擬機(jī)檢測到了非正常的執(zhí)行狀態(tài),這些狀態(tài)可能由三種因素之一引起: = 1 * GB3 表達(dá)式的計(jì)算違背了Java語言的語義,例如:數(shù)組越界、除數(shù)為0等。 = 2 * GB3 在載入和鏈接Java程序時(shí)出現(xiàn)錯(cuò)誤。 = 3 * GB3 超出了系統(tǒng)的資源限制,例如使用了太多的內(nèi)存這些無法預(yù)知的異常。2Java程序代碼中的throw語句被執(zhí)行。3發(fā)生異步異常,其可能的原因有Thread類的stop方法被調(diào)用;JVM內(nèi)部發(fā)生錯(cuò)誤;運(yùn)行時(shí)庫出現(xiàn)了內(nèi)部錯(cuò)誤等。三Java異常處理的優(yōu)點(diǎn)在面向過程的傳統(tǒng)語言中對(duì)程序中可能出現(xiàn)的錯(cuò)誤一般采取:查錯(cuò)、報(bào)錯(cuò)和排錯(cuò)的處理錯(cuò)誤代碼和常規(guī)代碼混雜在一起的方法

23、。比方在C語言面向過程的一種編程語言中輸出流的處理偽代碼是:建立一個(gè)文件輸入流;if(建立不成功) 報(bào)錯(cuò);處理錯(cuò)誤;else 從輸入流中讀入一個(gè)字符; if(讀入不成功) 報(bào)錯(cuò);處理錯(cuò)誤;關(guān)閉該文件的輸入流if(關(guān)閉不成功) 報(bào)錯(cuò);處理錯(cuò)誤; else else 經(jīng)過這樣的處理,程序可以保證正常地運(yùn)行。但是程序的每一步都要考慮是否會(huì)發(fā)生錯(cuò)誤,出現(xiàn)了錯(cuò)誤又該如何處理的問題。這不但使程序代碼的行數(shù)大大增加,而且,處理錯(cuò)誤代碼和正常代碼混雜在一起,使程序流程變得十分復(fù)雜,不利于閱讀。此外,它對(duì)于同一類型的錯(cuò)誤也不方便進(jìn)行統(tǒng)一的處理。于上面等價(jià)實(shí)現(xiàn)地面向?qū)ο笳Z言處理異常的偽代碼為:try 建立一個(gè)文件

24、輸入流;讀取一個(gè)字符;關(guān)閉該輸入流;catch( 文件輸入流翻開失敗 ) 報(bào)錯(cuò);處理錯(cuò)誤; catch( 讀入字符失敗 ) 報(bào)錯(cuò);處理錯(cuò)誤;面向?qū)ο笳Z言的異常處理對(duì)于面向過程語言處理錯(cuò)誤的方法有三種好處:其一將處理錯(cuò)誤代碼和正常代碼別離;其二能夠?qū)惓Q刂{(diào)用堆棧向上傳播;其三能按異常類型和異常對(duì)象分組。四 Java異常處理技術(shù)及其應(yīng)用一拋出異常如果有一個(gè)現(xiàn)成或者已定義的異??梢允褂?,那么拋出異常很容易。只要滿足以下三點(diǎn):1找到一個(gè)恰當(dāng)?shù)漠惓n?構(gòu)造一個(gè)該類的實(shí)例3拋出該實(shí)例比方我們經(jīng)常遇到IOException異常發(fā)生,其中它的一個(gè)子類是EOFException,就是描述在輸入過程中碰到一個(gè)

25、未預(yù)期的文件結(jié)尾標(biāo)志,我們拋出該異常的方法如下:throw new EOFException ( );或者這樣:EOFException e = new EOFException ( );throw e ;二捕獲異常 要想捕獲一個(gè)異常,需要設(shè)置一個(gè)try/catch的代碼塊。try塊的最簡單形式如下: try codemore codecatch (ExceptionType e ) handler for this type如果try塊內(nèi)的任何代碼拋出了由catch塊中指定的異常,那么程序跳過try塊中的其它代碼,程序執(zhí)行catch塊中的處理代碼。假設(shè)try塊沒有任何代碼拋出異常,那么程序會(huì)

26、直接跳過catch塊的內(nèi)容。當(dāng)然,可以在try塊同時(shí)捕獲多個(gè)異常,并分別對(duì)每種類型加以不同的處理。三堆棧幀在前,通過使用Throwable類的printStacktrace方法來獲得堆棧結(jié)構(gòu)的文本描敘。現(xiàn)在,可以通過調(diào)用getStackTrace方法來獲得一個(gè)StackTraceElement對(duì)象的數(shù)組,通過研究該數(shù)組,就可以分析程序運(yùn)行情況。例如:Throwable t = new Throwable ( );StackTraceElement frames = t.getStackTrace ( );For ( int i= 0;iframes.length;i+) 使用StackTrac

27、eElement類提供的方法獲取文件名以及當(dāng)前執(zhí)行的代碼行行號(hào)的方法,同樣,它還提供獲取類名、方法名的方法。而toString方法可以產(chǎn)生一個(gè)格式化字符串,其中包含那些獲得的信息。以下程序輸出一個(gè)遞歸調(diào)用方法的堆棧情況。import java.util.*;import javax.swing.*;public class StackTest /* 返回 n! = 1 * 2 * . . . * n 的結(jié)果 */ public static int factorial (int n) System.out.println (factorial ( + n + ): ) ; Throwable

28、t = new Throwable( ); StackTraceElement frames = t.getStackTrace(); for ( int i = 0 ;i frames.length; i+ ) System.out.println( frames i ); int r ; if (n = 1) r = 1; else r = n * factorial(n - 1); / 遞歸調(diào)用factorial方法 System.out.println(return + r); return r; public static void main(String args) String

29、input = JOptionPane.showInputDialog( 請(qǐng)輸入一個(gè)整數(shù): ); int n =Integer.parseInt(input); factorial(n); System.exit( 0 ); /退出程序 由于需要從標(biāo)準(zhǔn)輸入中獲取整數(shù)數(shù)字,Integer.ParseInt(input)方法可能會(huì)產(chǎn)生異常。運(yùn)行程序時(shí)界面:圖31 輸入界面如果我們要實(shí)現(xiàn)遞歸方法factorial(3),通過getStackTrace方法可以查看程序運(yùn)行的過程。其結(jié)果為如下: 圖32 遞歸方法factorial(3)的輸出結(jié)果而這個(gè)程序可能產(chǎn)生的一個(gè)異常是NumberFormatEx

30、ception異常。當(dāng)異常產(chǎn)生后,JVM調(diào)用該異常處理。其運(yùn)行界面如下:圖33 輸入一個(gè)產(chǎn)生異常的數(shù)據(jù)返回到控制臺(tái)的結(jié)果為描述該異常:圖34 輸入異常數(shù)據(jù)時(shí)在控制臺(tái)產(chǎn)生的結(jié)果四自定義異常由于在Java中,異常也被看成是對(duì)象,而且異常和一般的對(duì)象沒有什么不同。因此,任何類都可以定義它自己的異常,并用throw語句引發(fā)它們。其中,throw語句由帶有一個(gè)對(duì)象的關(guān)鍵字throw組成,這個(gè)對(duì)象應(yīng)該是Exception或其子類的一個(gè)實(shí)體對(duì)象。要注意的是,當(dāng)執(zhí)行了一條throw語句后,就不會(huì)執(zhí)行該語句之后的任何代碼了。通常每個(gè)異常類提供一個(gè)默認(rèn)的構(gòu)造器以及一個(gè)包含詳細(xì)信息的構(gòu)造器。使用Throwable的

31、toString方法會(huì)輸出該詳細(xì)信息,這個(gè)方法對(duì)代碼調(diào)試是很有用處。例如創(chuàng)立這樣的異常類:class FileFormatException extends IOException public FileFormatException ( ) public FileFormatException ( ) super ( gripe) ; String readData ( BufferedReader in ) throws FileFormatException while ( ) if ( ch=-1) /EOF標(biāo)記,即文件結(jié)尾 if (nlen) throw new FileFormat

32、Exception ( ); /拋出自定義的異常類FileFormatException return s; 五關(guān)于圖形界面程序的異常捕獲對(duì)于一個(gè)非圖形界面的程序而言,如果一個(gè)異常沒有被捕獲,那么程序會(huì)終止運(yùn)行并且在控制臺(tái)輸出一條包含異常類型以及堆棧內(nèi)容的信息。而對(duì)于具有圖形界面的程序包含applet以及應(yīng)用程序,也會(huì)輸出這些錯(cuò)誤信息,但是程序會(huì)返回用戶界面外層循環(huán)中去。下面我們從一個(gè)有趣的程序-顏色調(diào)和板來討論圖形界面程序處理異常的情況。在源代碼見附錄中,程序可以根據(jù)我們輸入紅色、綠色、藍(lán)色RGB、亮度、飽和度和色度值來調(diào)節(jié)顏色。整個(gè)程序除了可能會(huì)產(chǎn)生RuntimeException異常外,

33、這個(gè)程序還會(huì)產(chǎn)生NumberFormatException異常。當(dāng)然這是已檢查型異常。下面我們來看它在JVM中的運(yùn)行情況:圖41 輸入正常數(shù)據(jù)時(shí)的顏色調(diào)和板當(dāng)我們改變紅色值為非法的一個(gè)輸入,比方:“AB時(shí),其運(yùn)行結(jié)果為如下:圖42 輸入一個(gè)產(chǎn)生異常的數(shù)據(jù)顏色未變化,好似程序發(fā)生邏輯錯(cuò)誤似的沒有按照我們希望的去運(yùn)行其實(shí)程序已將控制權(quán)轉(zhuǎn)到控制中心去了,這個(gè)圖形還處于初始化階段在輸入“AB前。在控制中心我們發(fā)現(xiàn)如下一些異常發(fā)生描述:圖43 異常產(chǎn)生后返回到控制臺(tái)的說明 這說明發(fā)生了NumberFormatException數(shù)字格式異常異常后,并沒有繼續(xù)往下執(zhí)行代碼。由于數(shù)字格式異常為已檢查型異常,直

34、接調(diào)用系統(tǒng)的方法處理了。JVM報(bào)告程序發(fā)生了數(shù)字格式異常產(chǎn)生,并將其具體的情況報(bào)告給用戶。但是,是不是這個(gè)程序不能再接受正常的輸入數(shù)據(jù)運(yùn)行呢?還是必須要重新啟動(dòng)才能運(yùn)行?我們將“紅色值由“AB改為“200后發(fā)現(xiàn)顏色改變,這說明該程序還能運(yùn)行。結(jié)果如下列圖:圖44 將產(chǎn)生異常的輸入數(shù)據(jù)更改后的顏色調(diào)和板可見當(dāng)輸入了正常的數(shù)據(jù)后,程序就像第一次運(yùn)行一樣,可以正確的顯示顏色了。我們得到的結(jié)論是:局部Java圖形界面程序發(fā)生異常后不需要重新初始化,依舊可以運(yùn)行,但必須不再有異常發(fā)生。五 Java異常處理根本原那么合理使用Java異常機(jī)制可以使程序健壯而清晰,但是,Java異常處理機(jī)制也常常會(huì)被錯(cuò)誤地使

35、用,下面就討論一些關(guān)于使用異常的原那么:(一)不要忽略已檢查型異常注意下面的代碼:try method1(); /method1拋出Exception Acatch(Exception A) /捕獲Exception Ae.rintStackTrace( ); /打印捕獲異常上面的代碼似乎沒有什么問題,捕獲異常后將異常打印,然后繼續(xù)執(zhí)行。事實(shí)上在catch塊中對(duì)發(fā)生的異常情況并沒有作任何處理。雖然程序能夠繼續(xù)執(zhí)行,但是由于這里的操作已經(jīng)發(fā)生異常,將會(huì)導(dǎo)致以后的操作不能按照預(yù)期的情況開展下去,可能導(dǎo)致兩個(gè)結(jié)果。一種情況是這里的異常導(dǎo)致在程序中別的地方拋出一個(gè)異常,這會(huì)使程序員在調(diào)試時(shí)感到迷惑,因

36、為新的異常拋出的地方并不是程序真正發(fā)生問題的地方,也不是發(fā)生問題的真正原因。另外一種情況程序繼續(xù)運(yùn)行,并得出一個(gè)錯(cuò)誤的輸出結(jié)果,這種問題更加難以捕捉,因?yàn)楹芸赡馨阉?dāng)成一個(gè)正確的輸出。那么應(yīng)該如何處理呢?一般有四個(gè)選擇:處理異常,進(jìn)行修復(fù)以讓程序繼續(xù)執(zhí)行;重新拋出異常,在對(duì)異常進(jìn)行分析后發(fā)現(xiàn)這里不能處理它,那么重新拋出異常,讓調(diào)用者處理;將異常轉(zhuǎn)換為用戶可以理解的自定義異常再拋出,這時(shí)應(yīng)該注意不要喪失原始異常信息;不要捕獲異常。因此,當(dāng)捕獲一個(gè)未檢查型異常時(shí),必須對(duì)異常進(jìn)行處理;如果認(rèn)為不必要在這里作處理,就不要捕獲該異常,在方法體中聲明方法拋出異常,由上層調(diào)用者來處理該異常。(二)不要一次捕

37、獲所有的異常我們常見如下關(guān)于異常處理的代碼:trymethod1(); /method1拋出ExceptionAmethod2(); /method2拋出ExceptionBmethod3(); /method3拋出ExceptionCcatch(Exception e) /捕獲所有異常 代碼中使用一個(gè)catch子句捕獲了所有異常,看上去很簡潔,一個(gè)代碼段就捕獲了全部的異常。但是這里有兩個(gè)潛在的缺陷,一是對(duì)try塊中拋出的每種異常,很可能需要不同的處理和恢復(fù)措施,而由于這里只有一個(gè)catch塊,分別處理就不能實(shí)現(xiàn)。二是try塊中還可能拋出RuntimeException,代碼中捕獲了所有可能拋

38、出的RuntimeException而沒有作任何處理,掩蓋了編程的錯(cuò)誤,會(huì)導(dǎo)致程序難以調(diào)試。我們應(yīng)該處理為以下的代碼:trymethod1();method2();method3();catch (ExceptionA e)/分別捕獲和處理三種異常 catch (ExceptionB e) catch (ExceptionC e) (三)使用finally塊釋放資源關(guān)鍵字finally保證程序使用任何方式離開try塊,finally塊中的語句都會(huì)被執(zhí)行。當(dāng)程序中使用了外界資源,如數(shù)據(jù)庫連接、文件等,將釋放這些資源的代碼寫入finally塊中是很好的處理方式。必須注意的是,在finally塊中不

39、能拋出異常。Java異常處理機(jī)制保證在任何情況下必須先執(zhí)行finally塊然后再離開try塊,因此在try塊中發(fā)生異常的時(shí)候,Java虛擬機(jī)先轉(zhuǎn)到finally塊執(zhí)行finally塊中的代碼,finally塊執(zhí)行完畢后,再向外拋出異常。如果在finally塊中拋出異常,try塊捕捉的異常就不能拋出,外部捕捉到的異常就是finally塊中的異常信息,而try塊中發(fā)生的真正的異常堆棧信息那么喪失了。Connectioncon = null;try con=dataSource.getConnection();/拋出數(shù)據(jù)庫異常catch(SQLException e ) /捕獲異常進(jìn)行一些處理后再將

40、數(shù)據(jù)庫異常拋出給調(diào)用者處理throw e;finally try con.close();catch(SQLException e) e.printStackTrace();由于con為null,finally塊有異常發(fā)生,從而使try塊中發(fā)生的異常堆棧信息喪失。其調(diào)用者會(huì)得到如下信息:myPackage.MyClass.method1(methodl.Java:266)(四)異常不能影響對(duì)象的狀態(tài)異常產(chǎn)生后不能影響對(duì)象的狀態(tài),這是異常處理中的一條重要規(guī)那么。一個(gè)函數(shù)中發(fā)生異常后,對(duì)象的狀態(tài)應(yīng)該和調(diào)用這個(gè)函數(shù)之前保持一致,以確保對(duì)象處于正確的狀態(tài)中。如果對(duì)象是不可變對(duì)象(指調(diào)用構(gòu)造函數(shù)創(chuàng)立后就

41、不能改變的對(duì)象),即創(chuàng)立后沒有任何方法可以改變對(duì)象的狀態(tài),那么異常發(fā)生后對(duì)象狀態(tài)肯定不會(huì)改變。如果是可變對(duì)象,必須在編程中注意保證異常不會(huì)影響對(duì)象狀態(tài)。有三個(gè)方法可以做到異常不能影響對(duì)象地狀態(tài):1將可能產(chǎn)生異常的代碼和改變對(duì)象狀態(tài)的代碼分開,先執(zhí)行可能產(chǎn)生異常的代碼,如果產(chǎn)生異常,就不執(zhí)行改變對(duì)象狀態(tài)的代碼。2對(duì)不容易別離產(chǎn)生異常代碼和改變對(duì)象狀態(tài)代碼的方法,定義一個(gè)recover方法,在異常產(chǎn)生后調(diào)用recover方法修復(fù)被改變的類變量,恢復(fù)方法調(diào)用前的類狀態(tài)。3在方法中使用對(duì)象的拷貝,這樣當(dāng)異常發(fā)生后,被影響的只是拷貝,對(duì)象本身不會(huì)受到影響。(五)注意喪失或忽略的異常 在程序設(shè)計(jì)中,可以喪

42、失忽略一些異常,但是為了以后更好地維護(hù)代碼,最好不要喪失異常。比方下面的代碼:public void method2( ) trymethod1( ); /method1進(jìn)行了數(shù)據(jù)庫操作catch( SQLException e )/捕獲數(shù)據(jù)庫異常后將該異常封裝為/MyException后重新拋出throw new MyException(“發(fā)生了數(shù)據(jù)庫異常: +e.getMessage);public void method3( ) trymethod2( ); /調(diào)用method2(),拋出MyExceptioncatch (MyException e)e.printStackTrace(

43、 );在method2的代碼中,try塊捕獲method1拋出的數(shù)據(jù)庫異常SQLException后,拋出了新的自定義異常MyException。這段代碼是似乎沒有什么問題,但在控制臺(tái)的輸出卻是:MyException:發(fā)生了數(shù)據(jù)庫異常:對(duì)象名稱“MyTable無效atMyClass.method2(MyClass.Java:232)atMyClass.method3(MyClass.Java:255)原始異常SQLException的信息喪失了,這里只能看到method2里面定義的MyException的堆棧情況,而method1中發(fā)生的數(shù)據(jù)庫異常的堆棧那么看不到。如何排錯(cuò)呢?只有在meth

44、od1的代碼行中一行行去尋找數(shù)據(jù)庫操作語句。JDK的開發(fā)者們也意識(shí)到了這個(gè)情況,在中,Throwable類增加了兩個(gè)構(gòu)造方法,public Throwable ( Throwablecause)和public Throwable ( Stringmessage, Throwablecause ),在構(gòu)造函數(shù)中傳入的原始異常堆棧信息將會(huì)在printStackTrace方法中打印出來。但在中就只能靠程序員來實(shí)現(xiàn)打印原始異常堆棧信息了。實(shí)現(xiàn)過程也很簡單,只需要在自定義的異常類中增加一個(gè)原始異常字段,在構(gòu)造函數(shù)中傳入原始異常,然后重載printStackTrace方法,首先調(diào)用類中保存的原始異常的pr

45、intStackTrace方法,然后再調(diào)用方法就可以打印出原始異常信息了??梢赃@樣定義前面代碼中出現(xiàn)的MyException類:public class MyException extends Exceptionpublic SMException ( Throwable cause )/構(gòu)造函數(shù)this.cause1=cause;public MyException ( Strings ,Throwable cause )super(s);this.cause1=cause;/重載printStackTrace方法,打印出原始異常堆棧信息public void printStackTrace

46、()if(cause1!=null)cause1.printStackTrace();super.printStackTrace(s);public void printStackTrace(PrintStream s)if(cause1!=null)cause1.printStackTrace(s); super.printStackTrace(s);public void printStackTrace( PrintWriter s )if(cause1!=null)cause1.printStackTrace(s);super.printStackTrace(s);private Thr

47、owable cause1;(六)不要同時(shí)使用異常機(jī)制和返回值來處理異常我們可能會(huì)使用類似下面一段代碼:trydoSomething( );catch(MyException e)if(e.getErrcode=-1) if(e.getErrcode=-2) 假設(shè)過一段時(shí)間再來閱讀這段代碼,你很難弄明白程序的意思?;旌鲜褂肑ava異常處理機(jī)制和返回值使程序的異常處理局部變得混亂,并難以理解。在程序中,如果有多種不同的異常情況,就應(yīng)該定義多種不同的異常,而不要像上面代碼那樣。綜合使用Exception和返回值。處理應(yīng)該如下:try doSomething( );/doSomething()拋出M

48、yExceptionA和MyExceptionBcatch(MyExceptionA e) /捕獲異常分別進(jìn)行處理 catch(MyExceptionB e) (七)不要讓try塊過于龐大有人習(xí)慣用一個(gè)龐大的try塊包含所有可能產(chǎn)生異常的代碼,這樣有兩個(gè)害處:一是閱讀代碼的時(shí)候,在try塊冗長的代碼中,不容易知道到底是哪些代碼會(huì)拋出哪些異常,不利于代碼維護(hù);二是使用try捕獲異常是以程序執(zhí)行效率為代價(jià)的,將不需要捕獲異常的代碼包含在try塊中,影響了代碼執(zhí)行的效率。因此,在Java程序中最好將try塊編寫得簡潔些。六 結(jié)束語Java是一種面向?qū)ο蟮某绦蛟O(shè)計(jì)語言,Java的異常處理機(jī)制非常出色。

49、Java中的所有異常都是從根底類Throwable里繼承而來的,所以可確保我們得到的是一個(gè)通用接口。丟棄一個(gè)錯(cuò)誤的異常后,Java異常標(biāo)準(zhǔn)是在編譯期間檢查并執(zhí)行的。被取代的方法必須遵守那一方法的根底類的異常標(biāo)準(zhǔn)。Java可丟棄指定的異?;蛘邚闹付ó惓Q苌鰜淼钠渌惓?。這樣一來,運(yùn)用try/catch/finally異常處理機(jī)制,最終得到的是更為“健壯的異常控制代碼。Java異常處理為大的程序工程帶來很好的健壯性。當(dāng)然,在寫本論文時(shí),由于對(duì)Java的學(xué)習(xí)沒到達(dá)深入、精通程度,掌握J(rèn)ava異常處理技術(shù)也不是很全面,故而論文中對(duì)Java圖形程序的異常處理方面和Java異常處理機(jī)制具體實(shí)現(xiàn)的討論仍有

50、缺乏之處有待以后改良。致謝參考文獻(xiàn)1Bloch . Java Programming Language Guide.北京:機(jī)械工業(yè)出版社,2001.2Cay S.Horstmann .Core Java 2(第6版) .北京:機(jī)械工業(yè)出版社,2004.3Rogers Cadenhead ,Laura Lemay.Teach Yourself Java 2 In 21days.北京:人民郵電出版社,2004.4朱福喜,唐曉軍.Java程序設(shè)計(jì)技巧與實(shí)例.北京:人民郵電出版社,2004.5譚浩強(qiáng),程龍,楊海蘭,吳功宜.Java編程技術(shù).北京:人民郵電出版社,2003.6彭晨陽.Java實(shí)用系統(tǒng)開發(fā)

51、指南. 北京:機(jī)械工業(yè)出版社,2003.7Java 2 SDK Standard Edition Documentation9Java 2 程序設(shè)計(jì).北京:清華大學(xué)出版社,2004.10Kalthy Sierra,Bert Bates.Java 2學(xué)習(xí)指南.北京:人民郵電出版社,2004.11耿祥義.Java根底教程.北京:清華大學(xué)出版社,2004.12朱福喜. HYPERLINK :/ ptpress /books/Book_Information.asp?BID=11746 Java程序設(shè)計(jì)技巧與開發(fā)實(shí)例.北京:人民郵電出版社,2004.13謝小樂.J2EE經(jīng)典實(shí)例詳解.北京:人民郵電出版

52、社,2003.14Y.Daniel Liang.Java語言程序設(shè)計(jì)(第三版).北京:機(jī)械工業(yè)出版社,2005.15Bruce Eckel.Java編程思想. 北京:機(jī)械工業(yè)出版社,2005.附錄、源代碼 的源代碼:import java.awt.*;import java.awt.event.*;import javax.swing.*;public class SwingColorTest extends JFrame SwingColorControls RGBcontrols, HSBcontrols; JPanel swatch; public SwingColorTest() su

53、per(顏色調(diào)和板); setSize(400, 100); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel pane = new JPanel(); GridLayout grid = new GridLayout(1, 3, 5, 15); pane.setLayout(grid); /使用網(wǎng)格布局 swatch = new JPanel(); swatch.setBackground(Color.black); String rgbLabels = 紅色, 綠色, 藍(lán)色 ; RGBcontrols = new SwingCol

54、orControls(this, rgbLabels); String hsbLabels = 色調(diào), 飽和度, 亮度 ; HSBcontrols = new SwingColorControls(this, hsbLabels); pane.add(swatch); pane.add(RGBcontrols); pane.add(HSBcontrols); setContentPane(pane); pack(); setVisible(true); /main函數(shù) public static void main(String arguments) JFrame frame = new Sw

55、ingColorTest(); /RGB和HSB的相互轉(zhuǎn)換 void update(SwingColorControls control) Color c; / 從輸入文本框中獲得數(shù)據(jù) int value = new int3; for (int i = 0; i 3; i+) valuei = Integer.parseInt(control.settingi.getText(); if ( (valuei 255) ) valuei = 0; control.settingi.setText( + valuei); if (control = RGBcontrols) c = new Color(value0, value1, value2); /轉(zhuǎn)化為HSB float hsbValues = new float3; float HSB = Color.RGBtoHSB(value0, value1, value2,hsbValues); HSB0 *= 360; HSB1 *= 100; HSB2 *= 100; for (int i = 0; i 3; i+) HSBcontrols.settingi.setText(String.

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論