《Java語(yǔ)言程序設(shè)計(jì)案例教程》課件第7章_第1頁(yè)
《Java語(yǔ)言程序設(shè)計(jì)案例教程》課件第7章_第2頁(yè)
《Java語(yǔ)言程序設(shè)計(jì)案例教程》課件第7章_第3頁(yè)
《Java語(yǔ)言程序設(shè)計(jì)案例教程》課件第7章_第4頁(yè)
《Java語(yǔ)言程序設(shè)計(jì)案例教程》課件第7章_第5頁(yè)
已閱讀5頁(yè),還剩82頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

第7章異常處理7.1異常處理7.2用戶自定義異常類第7章異常處理學(xué)習(xí)目標(biāo)

掌握J(rèn)ava語(yǔ)言中異常的概念;

了解異常的處理機(jī)制;

了解Java語(yǔ)言中的異常類;

掌握try、catch和finally語(yǔ)句的用法;

學(xué)會(huì)自定義異常類。程序設(shè)計(jì)屬于邏輯思維的范疇,即使是一個(gè)非常有經(jīng)驗(yàn)的程序員,也難免會(huì)出現(xiàn)編程錯(cuò)誤。因此,為了使程序即使在有“問(wèn)題”的時(shí)候也能正常運(yùn)行,往往要耗費(fèi)程序設(shè)計(jì)人員很大的精力。Java語(yǔ)言為軟件開(kāi)發(fā)人員提供了一種非常方便與有效的異常處理機(jī)制,利用這種機(jī)制可以將程序的功能代碼與異常處理代碼有效分開(kāi),使程序結(jié)構(gòu)清晰,易于維護(hù)。本章介紹Java語(yǔ)言中異常處理的概念、異常的處理機(jī)制和設(shè)計(jì)異常處理類的方法。7.1異常處理在第1章調(diào)試Java程序的基本技能中介紹過(guò),程序中的錯(cuò)誤可分為三類:編譯錯(cuò)誤、運(yùn)行時(shí)錯(cuò)誤和邏輯錯(cuò)誤。編譯錯(cuò)誤是由于沒(méi)有遵循Java語(yǔ)言的語(yǔ)法規(guī)則而產(chǎn)生的,這種錯(cuò)誤要在編譯階段排除,否則程序無(wú)法運(yùn)行。發(fā)生邏輯錯(cuò)誤時(shí),程序編譯正常,也能運(yùn)行,但結(jié)果不是人們所期待的。舉一個(gè)簡(jiǎn)單的例子來(lái)說(shuō),如果程序要求a與b兩個(gè)數(shù)的和,但因表達(dá)式寫(xiě)錯(cuò),而求出的結(jié)果是a與b兩個(gè)數(shù)的差。對(duì)于程序邏輯上的這種錯(cuò)誤,要靠程序員對(duì)程序中的邏輯進(jìn)行仔細(xì)分析來(lái)加以排除。而運(yùn)行時(shí)錯(cuò)誤是指程序運(yùn)行過(guò)程中出現(xiàn)了一個(gè)不可能執(zhí)行的操作。運(yùn)行時(shí)錯(cuò)誤有時(shí)也可以由邏輯錯(cuò)誤引起。異常處理的主要目的是,即使在程序運(yùn)行時(shí)發(fā)生了錯(cuò)誤,也要保證程序能正常結(jié)束,避免因錯(cuò)誤而使正在運(yùn)行的程序中途停止。7.1.1異常的有關(guān)概念與異常處理機(jī)制

1.異常程序運(yùn)行過(guò)程中出現(xiàn)的非正常情況通常有兩類:●錯(cuò)誤(Error):是致命性的,如程序運(yùn)行過(guò)程中內(nèi)存不足等,這種嚴(yán)重的不正常狀態(tài)不能恢復(fù)執(zhí)行。●異常(Exception):是非致命性的,如數(shù)組下標(biāo)越界、表達(dá)式的分母為0等。這種不正常狀態(tài)可通過(guò)恰當(dāng)?shù)木幊潭钩绦蚶^續(xù)運(yùn)行。異常有時(shí)也稱為例外。致命性的錯(cuò)誤一般很少出現(xiàn),即使出現(xiàn)了這類錯(cuò)誤,在程序中也不進(jìn)行處理。一般程序中需要處理的主要是非致命性錯(cuò)誤,即異常。那么一個(gè)程序出現(xiàn)異常情況時(shí),會(huì)有什么現(xiàn)象呢?看下面一個(gè)簡(jiǎn)單的實(shí)例程序:1publicclassZero{2 publicstaticvoidmain(String[]args){3 System.out.println(10/0);4 System.out.println("程序運(yùn)行結(jié)束!");5 }6}該程序的第3行要求“10/0”表達(dá)式的結(jié)果,由于分母為0,因而該式無(wú)法正常運(yùn)算。程序執(zhí)行后輸出如下結(jié)果:Exceptioninthread"main"java.lang.ArithmeticException:/byzero

atZero.main(Zero.java:3)由于程序中沒(méi)有處理異常情況的代碼,因此當(dāng)程序出現(xiàn)異常時(shí)將終止執(zhí)行,同時(shí)系統(tǒng)自動(dòng)輸出一條有關(guān)此異常的描述信息。注意,該程序的第4行前已經(jīng)出現(xiàn)了錯(cuò)誤,所以第4行輸出字符串的語(yǔ)句將永遠(yuǎn)得不到執(zhí)行。上面輸出的第1行信息說(shuō)明,在main方法中出現(xiàn)了類型為“java.lang.ArithmeticException”的異常(表示一個(gè)算術(shù)運(yùn)算異常),異常的原因?yàn)椤?byzero”,即用0做除數(shù)。第2行表示調(diào)用Zero.main方法時(shí)產(chǎn)生了異常(在程序Zero.java的第3行)。以上異常的傳統(tǒng)糾正方法是在進(jìn)行除法運(yùn)算之前,先判斷除數(shù)是否為0,然后根據(jù)判斷情況進(jìn)行適當(dāng)?shù)奶幚?。如果一個(gè)程序有很多這樣的處理代碼,則會(huì)使程序的處理邏輯顯得雜亂無(wú)章,甚至?xí)胍恍┢渌e(cuò)誤。如果使用Java的異常處理機(jī)制,則可以將異常處理代碼從程序中分離出來(lái),并可以將異常根據(jù)情況進(jìn)行分類,對(duì)不同的異常集中編寫(xiě)相應(yīng)的處理程序,從而保證了程序的安全性。

2.?Java語(yǔ)言中處理異常的機(jī)制作為一種面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言,Java語(yǔ)言中的異常與其他語(yǔ)言要素一樣,也是用對(duì)象來(lái)表示的。

Java語(yǔ)言的設(shè)計(jì)者將Java語(yǔ)言程序中可能出現(xiàn)的各種錯(cuò)誤與異常進(jìn)行了歸納與總結(jié),并將歸納與總結(jié)的結(jié)果定義成了一個(gè)個(gè)表示錯(cuò)誤與異常的類。每個(gè)類代表了一種運(yùn)行錯(cuò)誤,類中包含了代表該運(yùn)行錯(cuò)誤的信息和處理錯(cuò)誤的方法等。在Java程序的運(yùn)行過(guò)程中,如果發(fā)生了一個(gè)運(yùn)行錯(cuò)誤,則當(dāng)系統(tǒng)識(shí)別到這個(gè)運(yùn)行錯(cuò)誤正好與已經(jīng)定義好的某個(gè)異常類相對(duì)應(yīng)時(shí),系統(tǒng)就會(huì)自動(dòng)生成一個(gè)與該異常類對(duì)應(yīng)的實(shí)例對(duì)象(其中包含了該異常事件的類型和異常發(fā)生時(shí)程序的運(yùn)行狀態(tài)),這時(shí)我們就說(shuō)系統(tǒng)產(chǎn)生了一個(gè)異常。一旦在執(zhí)行某個(gè)方法時(shí)產(chǎn)生了一個(gè)異常類對(duì)象,運(yùn)行時(shí)系統(tǒng)就在該方法中查找異常處理程序,如果沒(méi)有找到,就查找調(diào)用了該方法的方法中是否有異常處理程序,這樣一直找下去,直到找到異常處理程序?yàn)橹埂_@樣就可以確保不會(huì)發(fā)生死機(jī)、程序運(yùn)行中斷等情況。下面介紹Java語(yǔ)言中預(yù)定義的異常類及其類的層次結(jié)構(gòu)。

3.異常類在Java編程語(yǔ)言中,異常類及其子類的層次結(jié)構(gòu)如圖7-1所示。從圖7-1中可以看出,Throwable類是Java語(yǔ)言中所有錯(cuò)誤或異常的超類,只有當(dāng)對(duì)象是此類(或其子類之一)的實(shí)例時(shí),才能通過(guò)Java虛擬機(jī)對(duì)其進(jìn)行異常處理。Throwable類位于java.lang包中,其他大多數(shù)定義具體異常的子類均放在各自的功能包中,如輸入/輸出異常類IOException及其子類就位于java.io包中。圖7-1異常類及其子類的層次結(jié)構(gòu)

1)?Throwable類

Throwable類主要用于描述異常發(fā)生的位置和異常的內(nèi)容,它有Error和Exception兩個(gè)基本子類。Throwable類中定義的成員方法均為公共的(public),因此所有異常類都可以使用這些成員方法。Throwable類的常用構(gòu)造方法是:Throwable(Stringmessage)該構(gòu)造方法以message的內(nèi)容作為錯(cuò)誤信息串(即對(duì)錯(cuò)誤信息的描述)來(lái)創(chuàng)建Throwable對(duì)象,并記錄異常發(fā)生的位置。

Throwable類定義的常用方法有:●?publicStringgetMessage():本方法返回字符串變量message的內(nèi)容,該內(nèi)容是對(duì)異常的描述信息?!?publicStringtoString():若當(dāng)前對(duì)象包含錯(cuò)誤信息,則本方法返回由三部分組成的字符串,即當(dāng)前對(duì)象的類名、一個(gè)冒號(hào)和一個(gè)空格、錯(cuò)誤信息字符串;若當(dāng)前對(duì)象未包含錯(cuò)誤信息,則僅返回當(dāng)前對(duì)象的類名?!?publicvoidprintStackTrace():該方法輸出的第一行是當(dāng)前對(duì)象toString()的返回值,其余各行輸出異常發(fā)生的地點(diǎn)和方法調(diào)用的順序。

2)?Error類

Error類描述致命性的系統(tǒng)錯(cuò)誤,如Java的內(nèi)部錯(cuò)誤、資源耗盡等情況。這類異常由Java系統(tǒng)直接處理,用戶程序不用理會(huì)這類異常。

3)?Exception類程序運(yùn)行時(shí)產(chǎn)生的所有非致命性異常都是Exception類的子類??梢詫xception類的子類分為兩個(gè)部分:一部分是RuntimeException類及其子類,稱為非檢查型異常;另外一部分是除RuntimeException類及其子類之外的所有其他類,稱為檢查型異常。

RuntimeException類表示一種程序在設(shè)計(jì)中出現(xiàn)的問(wèn)題。如在程序設(shè)計(jì)時(shí),由于考慮不周而使數(shù)組的下標(biāo)(或稱索引)超出了數(shù)組的界限(ArrayIndexOutOfBoundsException),用0做除數(shù)(ArithmeticException),引用了一個(gè)空值對(duì)象變量(NullPointException)等,對(duì)于這類運(yùn)行時(shí)異常,如果程序設(shè)計(jì)過(guò)程正確,則該異常是不會(huì)出現(xiàn)的,因此編譯器對(duì)這類異常在程序中是否進(jìn)行了處理不進(jìn)行檢查。下面是一個(gè)演示這種異常的實(shí)例:01classDemoException{02publicstaticvoidmain(String[]args){03int[]a={2,4};04m1(a); 05System.out.println("執(zhí)行了m1(a)");06}07staticvoidm1(int[]b){08 m2(b);09}10staticvoidm2(int[]c){11System.out.println(c[2]);12}13}程序中沒(méi)對(duì)異常進(jìn)行任何處理,程序能正確編譯,但在運(yùn)行時(shí)出現(xiàn)了如下的異常信息:Exceptioninthread"main"java.lang.ArrayIndexOutOfBoundsException:2atDemoException.m2(DemoException.java:11)atDemoException.m1(DemoException.java:8)atDemoException.main(DemoException.java:4)程序的第03行定義了一個(gè)有兩個(gè)元素的數(shù)組。第04行調(diào)用了靜態(tài)方法m1,調(diào)用m1方法的實(shí)參是數(shù)組a。第07行的m1方法又調(diào)用了第10行定義的m2方法,調(diào)用m2方法的實(shí)參是數(shù)組b,m2方法的第11行輸出數(shù)組中下標(biāo)為2的元素值。由于該數(shù)組只有兩個(gè)元素,最大下標(biāo)只能是1,因而程序執(zhí)行時(shí)輸出如上的運(yùn)行時(shí)異常信息。該信息表明程序中出現(xiàn)了一個(gè)ArrayIndexOutOfBoundsException類的運(yùn)行時(shí)異常,該異常由m2方法的第11行引發(fā)。其方法的調(diào)用順序是,在main方法的第4行調(diào)用m1方法,在m1方法的第8行調(diào)用m2方法。對(duì)于非檢查型異常,要求程序員在調(diào)試程序時(shí)進(jìn)行詳細(xì)分析,并加以排除。程序中對(duì)這類異常一般不進(jìn)行處理(如果需要的話也可以進(jìn)行處理),而由系統(tǒng)檢測(cè)并輸出異常的內(nèi)容。下面是幾個(gè)常見(jiàn)的非檢查型異常類的含義:●?ArithmeticException:在整數(shù)進(jìn)行除法運(yùn)算時(shí),如果除數(shù)為0,就會(huì)產(chǎn)生該類異常。例如:inti=10/0;●?NullPointerException:當(dāng)對(duì)象沒(méi)被實(shí)例化時(shí),訪問(wèn)對(duì)象的屬性或方法就會(huì)產(chǎn)生該類異常。例如:

String[]a=newString[2];

//聲明一個(gè)包含兩個(gè)字符串的數(shù)組

System.out.println(a[0].length());

//a[0]字符串還沒(méi)有創(chuàng)建,就調(diào)用求其長(zhǎng)度的方法●?NegativeArraySizeException:創(chuàng)建帶負(fù)維數(shù)大小的數(shù)組時(shí),就會(huì)產(chǎn)生該類異常。例如:int[]a=newint[-2];●?ArrayIndexoutofBoundsException:訪問(wèn)超過(guò)數(shù)組大小范圍的一個(gè)下標(biāo)元素時(shí),就會(huì)產(chǎn)生該類異常。如上面的實(shí)例。如果一個(gè)方法可能產(chǎn)生除RuntimeException類及其子類之外的其他檢查型異常,則在Java程序編譯時(shí)要對(duì)這類異常是否進(jìn)行了處理進(jìn)行檢查。當(dāng)編譯器檢查到程序中沒(méi)有對(duì)這類異常進(jìn)行處理時(shí),就會(huì)產(chǎn)生編譯錯(cuò)誤。下面介紹Java中對(duì)異常進(jìn)行處理的方法。

4.異常的處理對(duì)于檢查型異常,Java要求程序中必須進(jìn)行處理。具體處理方法有兩種:聲明拋出異常和捕獲異常。

1)聲明拋出異常如果在當(dāng)前方法中對(duì)產(chǎn)生的異常不想進(jìn)行處理,或者不能確切地知道該如何處理這一異常事件時(shí),可以使用throws子句將異常拋出,交給該方法的調(diào)用者進(jìn)行處理,當(dāng)然調(diào)用者也可以繼續(xù)將該異常拋出。聲明拋出異常是在一個(gè)方法聲明中用throws子句指明的。例如:publicintread()throwsjava.io.IOException{

...}表示read方法對(duì)IOException異常不進(jìn)行處理。IOException異常類是Java程序中要輸入或輸出信息時(shí)引發(fā)的異常。在throws子句中,同時(shí)可以指明多個(gè)要拋出的異常,多個(gè)異常之間用逗號(hào)隔開(kāi)。例如:publicstaticvoidmain(Stringargs[])throwsjava.io.IOException,IndexOutOfBoundsException{

…}表示main方法拋出IOException和IndexOutOfBoundsException異常。如果在main方法中也選擇了拋出異常,則Java虛擬機(jī)將捕獲該異常,在輸出相關(guān)異常信息后,中止程序的運(yùn)行。注意:子類中如果重寫(xiě)了父類中的方法,則子類方法中可聲明拋出的異常類只能是被重寫(xiě)方法中throws子句所拋出異常類的子集,也就是說(shuō),子類中重寫(xiě)的方法不能拋出比父類中方法更多的異常。例如:1classFather{2voidf()throwsjava.io.IOException{}3}4classSonextendsFather{5 voidf()throwsException{}6}該程序的子類Son在重寫(xiě)父類的f方法時(shí),聲明拋出的異常比父類第2行中f方法聲明拋出的異常范圍要大(因?yàn)镋xception異常類是IOException異常類的父類),所以在編譯該程序時(shí)就會(huì)產(chǎn)生編譯錯(cuò)誤。如果將第5行的Exception改為java.io.FileNotFoundException,則程序不會(huì)出現(xiàn)編譯錯(cuò)誤,因?yàn)镕ileNotFoundException(文件沒(méi)有找到異常)類是IOException異常類的子類。

2)在方法中捕獲并處理異常在一個(gè)程序中,應(yīng)對(duì)異常更積極的方法是將其捕獲并進(jìn)行處理。在方法中捕獲并處理異常要使用try/catch語(yǔ)句。try/catch語(yǔ)句的語(yǔ)法格式如下:try{//在此區(qū)域內(nèi)可能發(fā)生異常;}catch(異常類1e1){//處理異常1;}…catch(異常類nen){//處理異常n;}finally{//不論異常是否發(fā)生都要執(zhí)行的部分;}一個(gè)try塊后根據(jù)需要可以跟一個(gè)或多個(gè)進(jìn)行異常處理的catch塊,finally塊是可選的。在設(shè)計(jì)程序時(shí),要將可能發(fā)生異常的程序代碼放置在try語(yǔ)句塊中,將發(fā)生異常時(shí)的處理程序放在catch語(yǔ)句塊中。程序在正常運(yùn)行過(guò)程中,后面的各catch塊不起任何作用。如果try塊內(nèi)的代碼出現(xiàn)了異常,則系統(tǒng)將終止try塊代碼的執(zhí)行,自動(dòng)跳轉(zhuǎn)到與產(chǎn)生異常相匹配的catch塊中,執(zhí)行該塊中的代碼。例如:1try{2c=a/b;3System.out.println("try語(yǔ)句塊執(zhí)行結(jié)束");4}5catch(ArithmeticExceptione){6System.out.println("除數(shù)為0,a/b的結(jié)果無(wú)法求出!");7}如果b為0,則try塊中的程序產(chǎn)生ArithmeticException類的異常,第3行的輸出語(yǔ)句不會(huì)被執(zhí)行,程序自動(dòng)轉(zhuǎn)到第5行所指的catch塊中執(zhí)行異常處理程序。當(dāng)有多種類型的異常需要捕獲時(shí),一個(gè)try塊可以對(duì)應(yīng)多個(gè)catch塊。如果一個(gè)try塊對(duì)應(yīng)多個(gè)catch塊,當(dāng)try塊中產(chǎn)生異常時(shí),究竟會(huì)執(zhí)行哪個(gè)catch塊中的異常處理程序呢?這決定于try塊中產(chǎn)生的異常對(duì)象能與哪個(gè)catch塊中要捕獲的異常類相匹配。如果多個(gè)catch塊中要捕獲的異常類有子類與父類的關(guān)系,或有子類與祖先類的關(guān)系,則catch塊中異常類的順序要放置合理,否則程序在出現(xiàn)異常時(shí),可能不能正確運(yùn)行。在catch塊中,應(yīng)將特殊的異常類處理程序(即catch塊)放在前面,將一般的異常類處理程序放在后面。在異常類層次結(jié)構(gòu)樹(shù)中(如圖7-1所示),一般的異常類在頂層(圖7-1中靠左邊的類),特殊的異常類在底層(圖7-1中靠右邊的類)。如果一個(gè)異常類的順序放置不合理,則該catch塊中的語(yǔ)句可能永遠(yuǎn)也不會(huì)被執(zhí)行,例如:try{//可以引起異常的程序代碼}catch(Exceptione){//異常處理1}catch(ArithmeticExceptione){//異常處理2}如果在該程序的try塊中產(chǎn)生ArithmeticException類的異常,則首先被第一個(gè)catch塊捕獲,因?yàn)镋xception類是ArithmeticException類的間接父類。正確的順序是將ArithmeticException異常類放在前一個(gè)catch塊中。finally語(yǔ)句塊是個(gè)可選項(xiàng),如果包含有finally語(yǔ)句塊,則無(wú)論try塊是否產(chǎn)生異常,finally語(yǔ)句塊內(nèi)的代碼必定被執(zhí)行。由于try塊內(nèi)的語(yǔ)句在發(fā)生異常時(shí),產(chǎn)生異常之后的代碼不會(huì)被執(zhí)行,因此,如果程序中有些語(yǔ)句無(wú)論如何均要被執(zhí)行,則可以將這樣的代碼放在finally塊中。7.1.2【案例7-1】用異常處理機(jī)制重寫(xiě)計(jì)算器程序

1.案例描述見(jiàn)第3章案例3-4。

2.案例效果案例程序的執(zhí)行效果如圖7-2所示。圖7-2案例7-1的執(zhí)行效果

3.技術(shù)分析該案例中,從鍵盤(pán)上輸入的運(yùn)算式可能發(fā)生的錯(cuò)誤有如下幾種情況:●輸入的表達(dá)式不完整,如圖7-2的第1行。一個(gè)表達(dá)式由兩個(gè)操作數(shù)和一個(gè)運(yùn)算符組成,程序中這三個(gè)部分分別保存到了args[0]、args[1]和args[2],當(dāng)式子不完整時(shí),使用args[0]、args[1]和args[2]就會(huì)出現(xiàn)下標(biāo)元素越界的異常ArrayIndexOutOfBoundsException?!褫斎氲倪\(yùn)算數(shù)不是整數(shù),如圖7-2的第3行。如果輸入了其他的非整數(shù)數(shù)據(jù),則在使用Integer.parseInt()方法進(jìn)行數(shù)據(jù)格式轉(zhuǎn)換時(shí)就會(huì)產(chǎn)生NumberFormatException異常?!褫斎氲谋磉_(dá)式中除數(shù)為0,如圖7-2的第5行。除數(shù)為0時(shí)就會(huì)產(chǎn)生ArithmeticException異常?!褫斎氲谋磉_(dá)式運(yùn)算符不正確,如圖7-2的第7行。對(duì)于這種情況,系統(tǒng)沒(méi)有預(yù)定義的異常類,如果發(fā)生了這種情況,則在程序中生成一個(gè)異常。所有這些異??梢栽诔绦蛑羞M(jìn)行統(tǒng)一處理,即將可能產(chǎn)生異常的語(yǔ)句放入try塊中,在其后進(jìn)行捕獲并處理這些不同的異常。

4.程序解析下面是該案例的程序代碼:01//*********************************************02//案例:7-1程序名:SimpleCal2.java03//功能:簡(jiǎn)單的計(jì)算器,可以進(jìn)行兩個(gè)整數(shù)的加、減、乘、除運(yùn)算04//*********************************************0506classSimpleCal2{07 //operand1和operand2保存兩個(gè)運(yùn)算數(shù)據(jù)08 privateintoperand1,operand2;09 //operator保存運(yùn)算符10 privatecharoperator;11 12 SimpleCal2(){}13 14 //初始化運(yùn)算式的構(gòu)造方法15 SimpleCal2(intoperand1,charoperator,intoperand2){16 this.operand1=operand1;17 this.operand2=operand2;18 this.operator=operator;19 }20 21 //求運(yùn)算結(jié)果22 privateintcal()throwsArithmeticException,Exception{23 intresult=Integer.MIN_VALUE;24 if(operator=='+')25 result=operand1+operand2;26 elseif(operator=='-')27 result=operand1-operand2;28 elseif(operator=='*')29 result=operand1*operand2;30 elseif(operator=='/'){31 result=operand1/operand2;32 }33 else{34 thrownewException("輸入的運(yùn)算符錯(cuò)誤!");35 } 36 returnresult;37 }38 39 //輸出運(yùn)算式和運(yùn)算結(jié)果40 publicvoidshowResult()throwsArithmeticException,Exception{41 System.out.println("運(yùn)算結(jié)果:"+operand1+operator+operand2+"="+cal());42 }43 44 publicstaticvoidmain(String[]args){45 intp1,p2;46 try{47 p1=Integer.parseInt(args[0]);48 charop=args[1].charAt(0);49 p2=Integer.parseInt(args[2]);50 SimpleCal2exp=newSimpleCal2(p1,op,p2);51 exp.showResult();52 }53 catch(NumberFormatExceptione1){54 System.out.println("輸入的運(yùn)算數(shù)不是整數(shù)!");55 }56 catch(ArrayIndexOutOfBoundsExceptione2){57 System.out.println("輸入的運(yùn)算式不完整!");58 }59 catch(ArithmeticExceptione3){60 System.out.println(“除數(shù)為0,不能進(jìn)行除法運(yùn)算!");61 }62 catch(Exceptione4){63 e4.printStackTrace();64 }65 }66}該程序第22行定義的cal()方法,在進(jìn)行算術(shù)運(yùn)算時(shí)如果除數(shù)為0,則可能產(chǎn)生ArithmeticException類的算術(shù)運(yùn)算異常。用cal()方法進(jìn)行運(yùn)算時(shí),如果運(yùn)算符不是所要求的運(yùn)算符,則第34行在程序中主動(dòng)生成并拋出一個(gè)Exception類的異常,由thrownewException("輸入的運(yùn)算符錯(cuò)誤!")語(yǔ)句完成該功能(該知識(shí)點(diǎn)下面介紹),異常信息為Exception構(gòu)造方法中參數(shù)所給的內(nèi)容。對(duì)cal()方法中產(chǎn)生的這兩種異常并沒(méi)有進(jìn)行捕獲與處理,所以在cal()方法中聲明拋出這兩種異常,由調(diào)用該方法的程序進(jìn)行處理。在第40行定義的showResult()方法體中調(diào)用了cal()方法,因此,在該方法中應(yīng)該處理由cal()方法聲明拋出的異常。但該方法也沒(méi)有進(jìn)行異常捕獲與處理,而是將這兩種異常繼續(xù)聲明拋出“throwsArithmeticException,Exception”。在主方法main中調(diào)用了showResult()方法,因此對(duì)于showResult()方法聲明拋出的異常一定要進(jìn)行處理,如果不進(jìn)行處理,則只能在發(fā)生異常時(shí)中斷程序的運(yùn)行。在main方法中,將可能產(chǎn)生異常的語(yǔ)句放入了第46~52行的try塊中,第53~64行是對(duì)各種異常的處理程序。第63行調(diào)用異常類printStackTrace()方法輸出異常發(fā)生的信息和方法調(diào)用的先后次序。注意,一定要將Exception異常的處理語(yǔ)句放在catch塊的最后,否則其他的異常將無(wú)法被捕獲。7.1.3【相關(guān)知識(shí)】用戶創(chuàng)建并拋出系統(tǒng)預(yù)定義異常在一個(gè)程序中產(chǎn)生并拋出異常有兩種情況:一是當(dāng)程序中產(chǎn)生了一個(gè)系統(tǒng)可以識(shí)別的、預(yù)定義的異常類時(shí),由虛擬機(jī)生成并拋出異常對(duì)象,如ArithmeticException、ArrayIndexOutOfBoundsException等異常類;另一種情況是在程序中主動(dòng)產(chǎn)生一個(gè)異常對(duì)象(而非系統(tǒng)產(chǎn)生),然后使用throw語(yǔ)句拋出該異常對(duì)象,在方法中對(duì)這類異常也要進(jìn)行捕獲并處理。例如案例7-1程序代碼的第34行。又如:IOExceptione=newIOException();throwe;要注意,可以拋出的異常必須是Throwable類或其子類的實(shí)例。技能拓展7.2用戶自定義異常類在程序中除了經(jīng)常用到的系統(tǒng)預(yù)定義異常類,如用0作除數(shù)、下標(biāo)越界、數(shù)據(jù)格式錯(cuò)誤、輸入/輸出錯(cuò)誤等異常外,在具體開(kāi)發(fā)一個(gè)軟件時(shí)還可能會(huì)用到系統(tǒng)中沒(méi)有定義的異常,如成績(jī)管理軟件中學(xué)生的成績(jī)只能在0~100分之間(假如使用百分制計(jì)成績(jī)),如果超過(guò)這個(gè)范圍,則成績(jī)數(shù)據(jù)肯定有誤。對(duì)于這種情況,程序員可以根據(jù)實(shí)際需要自己設(shè)計(jì)異常類。7.2.1設(shè)計(jì)異常類

1.自定義異常類的格式在Java程序設(shè)計(jì)中,程序員可以自己定義一些異常類,稱之為用戶自定義異常類。用戶自定義的異常類必須繼承自Throwable類或其子類,比較常用的是繼承Exception類。其一般格式為class自定義異常類名extendsException{//異常類體;}自定義異常類如果繼承了異常類Exception,則Java就會(huì)將自定義的異常類視為檢查型異常。在一個(gè)方法中如果有這類異常產(chǎn)生,就一定要聲明拋出(throws),讓該方法的調(diào)用者處理,或者在該方法中直接捕獲并處理,否則程序在編譯時(shí)就會(huì)產(chǎn)生錯(cuò)誤,提示用戶沒(méi)有聲明或處理異常。下面的示例定義了一個(gè)簡(jiǎn)單的自定義異常類:1classMyExceptionextendsException{2 MyException(){3 }4 5 MyException(Stringmsg){6 super(msg);7 }8}程序的第2行定義了一個(gè)無(wú)參的構(gòu)造方法,第5行定義了帶一個(gè)字符串參數(shù)的構(gòu)造方法,該方法在第6行調(diào)用了父類帶一個(gè)參數(shù)的構(gòu)造方法。在自定義的異常類中,一般要聲明兩個(gè)構(gòu)造方法:一個(gè)是不帶參數(shù)的構(gòu)造方法;另一個(gè)是以字符串為參數(shù)的構(gòu)造方法。帶字符串參數(shù)的構(gòu)造方法以該字符串參數(shù)表示對(duì)異常內(nèi)容的描述,如果使用getMessage()方法,則可以返回該字符串。由于自定義異常類繼承了Exception類,也就擁有了Throwable類的除構(gòu)造方法以外的其它方法,因此在本章第1節(jié)中介紹的Throwable類中定義的方法都可以在自定義異常類中使用。

2.創(chuàng)建與拋出自定義異常如果程序中發(fā)生了系統(tǒng)預(yù)定義的異常類,則Java虛擬機(jī)會(huì)自動(dòng)生成并拋出該異常類的對(duì)象。而用戶自定義異常則要由用戶在程序中根據(jù)具體情況創(chuàng)建并拋出,才可以在程序中進(jìn)行捕獲和處理。自定義異常的創(chuàng)建就是使用已定義好的異常類生成該類的一個(gè)實(shí)例。例如對(duì)于MyException異常類,可以使用如下的語(yǔ)句創(chuàng)建一個(gè)該類的異常:MyExceptione=newMyException("這是自定義的一個(gè)異常類實(shí)例");創(chuàng)建好的異常類對(duì)象,只有拋出后才可以被程序捕獲。拋出創(chuàng)建的異常e時(shí),要使用throw語(yǔ)句:throwe;如果要拋出的異常只被使用一次,則可以將以上兩步用如下的簡(jiǎn)單格式書(shū)寫(xiě):thrownewMyException("這是自定義的一個(gè)異常類實(shí)例");7.2.2【案例7-2】統(tǒng)計(jì)學(xué)生成績(jī)分布情況

1.案例描述設(shè)計(jì)一個(gè)程序,從鍵盤(pán)上輸入學(xué)生的成績(jī),然后統(tǒng)計(jì)學(xué)生成績(jī)的分布情況。要求統(tǒng)計(jì)出0~9分,10~19分,20~29分,…,90~99分,100分各區(qū)段的成績(jī)個(gè)數(shù)。

2.案例效果案例7-2的部分執(zhí)行結(jié)果如圖7-3所示。第7行的字母“n”表示結(jié)束成績(jī)的錄入過(guò)程。圖7-3案例7-2的執(zhí)行結(jié)果

3.技術(shù)分析如果從鍵盤(pán)上輸入的學(xué)生成績(jī)小于0或者大于100分,就認(rèn)為是異常的成績(jī)。程序中若遇到異常成績(jī),該如何處理呢?在沒(méi)有學(xué)習(xí)異常處理知識(shí)之前,我們只能對(duì)成績(jī)判別后分情況進(jìn)行處理,程序結(jié)構(gòu)比較混亂。在本案例中,我們可以單獨(dú)設(shè)計(jì)一個(gè)表示學(xué)生成績(jī)異常的類(ScoreException),如果遇到成績(jī)小于0或者大于100分的情況,則生成并拋出一個(gè)異常,然后在異常處理程序塊(即catch塊)中單獨(dú)進(jìn)行處理。

4.程序解析下面是案例7-2的程序代碼:01//********************************************02//案例:7-2程序名:TestScoreException.java03//功能:統(tǒng)計(jì)學(xué)生的成績(jī)分布情況04//*********************************************0506importjava.util.Scanner;0708classScoreExceptionextendsException{09 privateintscore;10 11 publicScoreException(){}12 13 publicScoreException(Stringmsg,intscore){14 super(msg);15 this.score=score;16 }17 18 publicStringtoString(){19 if(score<0)20 returngetMessage()+":輸入的成績(jī)是負(fù)數(shù)。";21 else22returngetMessage()+":不能輸入大于100分的成績(jī)。";23 }24}2526classTestScoreException{27 publicstaticvoidmain(String[]args){28 int[]s=newint[11];29 input(s);30 print(s);31 }32 33 //輸出成績(jī)分布情況34 staticvoidprint(int[]s){35 System.out.println("\n學(xué)生成績(jī)分布情況如下:");36 for(inti=0;i<s.length;i++){37 if(i<10)38 System.out.print(i*10+"~"+(i*10+9)+":");39 else40 System.out.print(i*10+":");41 for(intk=0;k<s[i];k++){42 System.out.print("*");43 }44 System.out.println();45 } 46 }47 48 //錄入成績(jī),并將各區(qū)段學(xué)生的人數(shù)存放在數(shù)組s中49 staticvoidinput(int[]s){50 Scannersc=newScanner(System.in);51 inttemp;52 System.out.println(“請(qǐng)輸入成績(jī)后回車,結(jié)束輸入時(shí)按非數(shù)字鍵!");53 while(sc.hasNextInt()){54 55 try{56temp=sc.nextInt();57if((temp>100)||(temp<0))58thrownewScoreException("成績(jī)格式不正確",temp);59 s[temp/10]++;60 }61 catch(ScoreExceptione1){62 System.out.println(e1);63 }64 }65 }66}在程序中要使用Scanner類的實(shí)例輸入成績(jī),第06行引入java.util包中的Scanner類。第08~24行定義了一個(gè)用戶異常類ScoreException,該類繼承了Exception異常類。在ScoreException類中定義了一個(gè)私有數(shù)據(jù)成員和兩個(gè)構(gòu)造方法。數(shù)據(jù)成員score中存放學(xué)生的成績(jī)信息(其實(shí)該成績(jī)是一個(gè)不在0~100范圍的非法成績(jī))。兩個(gè)構(gòu)造方法中,一個(gè)是無(wú)參的構(gòu)造方法,另一個(gè)是帶兩個(gè)參數(shù)的構(gòu)造方法。在帶兩個(gè)參數(shù)的構(gòu)造方法中,第1個(gè)參數(shù)是對(duì)異常的描述,第2個(gè)參數(shù)是錄入的成績(jī)。第14行調(diào)用了父類帶一個(gè)參數(shù)的構(gòu)造方法。第18行重寫(xiě)了父類的toString方法,在第62行的輸出中,參數(shù)使用ScoreException類的一個(gè)對(duì)象名時(shí),會(huì)自動(dòng)調(diào)用該方法。第26~66行定義了TestScoreException類,該類的功能是輸入成績(jī),并統(tǒng)計(jì)各區(qū)段的成績(jī)個(gè)數(shù)。第28行定義的整型數(shù)組s共有11個(gè)下標(biāo)變量,這11個(gè)下標(biāo)變量與0~9分,10~19分,20~29分,…,90~99分,100分共11個(gè)分?jǐn)?shù)段對(duì)應(yīng),分別用于存放各區(qū)段的分?jǐn)?shù)個(gè)數(shù)。第29行調(diào)用input方法輸入學(xué)生成績(jī),并將各區(qū)段成績(jī)的個(gè)數(shù)存入?yún)?shù)數(shù)組s中。第30行調(diào)用print方法將參數(shù)s數(shù)組進(jìn)行輸出。在第49~65行定義的input方式中,第50行創(chuàng)建了一個(gè)Scanner類的實(shí)例sc,使用“System.in”作構(gòu)造方法的參數(shù),表示要從鍵盤(pán)上輸入數(shù)據(jù),第53行調(diào)用Scanner類中定義的hasNextInt方法,該方法表示輸入信息中的下一個(gè)標(biāo)記可以解釋為整數(shù)時(shí),hasNextInt方法返回true,只要輸入一個(gè)非整數(shù)的值,hasNextInt方法就返回false,該程序就是利用hasNextInt方法的這個(gè)特點(diǎn)來(lái)控制成績(jī)輸入的。當(dāng)最后一個(gè)成績(jī)輸入完成后,只要按鍵盤(pán)上的任一個(gè)字母鍵后回車,則成績(jī)的輸入過(guò)程結(jié)束(在圖7-3中按下了字母n)。第56行通過(guò)sc.nextInt()方法取得從鍵盤(pán)輸入的一個(gè)整數(shù),經(jīng)過(guò)第57行判別后,如果輸入的成績(jī)不在0~100之間,則第58行創(chuàng)建一個(gè)自定義異常類ScoreException的實(shí)例,構(gòu)造方法的第1個(gè)參數(shù)“成績(jī)格式不正確”是對(duì)異常的描述信息,第2個(gè)參數(shù)temp是錄入的成績(jī)。在異常類ScoreException中定義一個(gè)成績(jī)字段的原因,是在toString方法中要根據(jù)非法成績(jī)是負(fù)數(shù)還是大于100的數(shù)生成返回的異常描述信息,見(jiàn)第19行至22行。7.2.3【相關(guān)知識(shí)】finally之后的程序段是否可以被執(zhí)行的討論在finally塊之后的語(yǔ)句在一般情況下都會(huì)被執(zhí)行。在一些特殊情況下,雖然finally塊中的語(yǔ)句可以正常執(zhí)行,但在finally塊之后的語(yǔ)句可能永遠(yuǎn)也執(zhí)行不了。下面舉例說(shuō)明。

1.在catch塊產(chǎn)生了異常,但沒(méi)有被捕獲與處理看下面的示例程序:01classDemoException{02publicstaticvoidmain(String[]args){03int[]a={2,4};04try{05 a[2]=1;06System.out.println("tryblock.");07}08catch(Exceptione){09System.out.println("catchblock.");10a[0]=1/0;11}12finally{13System.out.println("finallyblock.");14}15System.out.println("out.");16}17}該程序執(zhí)行后的結(jié)果為:catchblock.finallyblock.Exceptioninthread"main"java.lang.ArithmeticException:/byzeroatDemoException.main(DemoException.java:10)程序中finally塊之后的第15行語(yǔ)句沒(méi)有被執(zhí)行。這種情況是由于在catch塊中的第10行產(chǎn)生了一個(gè)分母為0的異常,但并沒(méi)有在該catch塊中對(duì)該異常進(jìn)行捕獲與處理,因此將中斷main方法的執(zhí)行。注意,該程序中try塊中的第06行也沒(méi)有被執(zhí)行。要避免這種情況的發(fā)生,可以在catch塊中嵌套try-catch語(yǔ)句,將catch塊中產(chǎn)生的異常也捕獲,并進(jìn)行處理。

2.?try塊中產(chǎn)生的異常,沒(méi)有相應(yīng)的catch塊捕獲看下面的示例程序:01classDemoException2{02publics

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(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)論