




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)
文檔簡介
5.1異常分析及異常類
5.2異常處理
5.3小結(jié)
5.4習(xí)題
5.1.1一個有問題的程序
什么是異常?先來分析一個程序及其運(yùn)行結(jié)果。
【例5-1】除零異常程序。
publicclassDivideZero{
intx;
publicstaticvoidmain(String[]args){
intresult;
5.1異常分析及異常類
DivideZerok=newDivideZero();
result=35/k.x;
System.out.println("result="+result);
System.out.println("programendsok");
}
}
程序運(yùn)行結(jié)果如圖5-1所示。圖5-1DivideZero.java的運(yùn)行結(jié)果這個程序在編譯時不會出現(xiàn)問題,但是在運(yùn)行時出現(xiàn)了異常。通過提示信息可以知道,程序中第6行的位置出現(xiàn)了被0除的情況。再仔細(xì)考慮一下,原來在創(chuàng)建對象k的時候,其數(shù)據(jù)成員x被初始化成0,即k.x為0,而除0是非法的。
當(dāng)程序運(yùn)行時,會發(fā)生不正常的事件阻止事先設(shè)計(jì)好的程序的執(zhí)行,這些事件稱為異常。當(dāng)這個程序運(yùn)行到“35/k.x”時,Java拋出一個異常,該異常表示算術(shù)操作不能執(zhí)行,并且程序自動終止。Java拋出的這個異常為java.lang.ArithmeticException,是一個類。為什么運(yùn)行結(jié)果有錯誤信息的提示呢?這與Java處理異常的機(jī)制有關(guān)。當(dāng)Java拋出異常后,有幾件事會隨之發(fā)生。首先,同Java中其他對象的創(chuàng)建一樣,Java將使用new創(chuàng)建異常對象。然后,由于當(dāng)前的執(zhí)行路徑不能繼續(xù)下去了,所以該路徑被終止,并且彈出對異常對象的引用。此時,異常處理機(jī)制接管程序,并開始尋找一個恰當(dāng)?shù)牡胤絹砝^續(xù)執(zhí)行程序。這個恰當(dāng)?shù)牡胤骄褪恰爱惓L幚沓绦颉?,它的任?wù)是將程序從錯誤狀態(tài)中恢復(fù),以使程序要么換一種方式運(yùn)行,要么以原有方式繼續(xù)運(yùn)行下去。5.1.2異常類的組織
用面向?qū)ο蟮姆椒▉磉M(jìn)行異常處理,首先必須建立異常處理類的層次。在異常處理類層次的最上層有一個單獨(dú)的類叫做Throwable類,用來表示任何可以作為異常被拋出的類,每個異常類都是Throwable的子類。異常類的層次關(guān)系如下:
Throwable對象可分為兩種類型(從Throwable繼承而得到的類型):Error用來表示編譯和系統(tǒng)錯誤(除特殊情況外,一般不用程序員關(guān)心);Exception是可以被拋出的基本類型,在Java類庫、用戶方法以及運(yùn)行故障中都可能拋出Exception型異常。所以Java程序員關(guān)心的基類型通常是Exception。對于Java異常類的全面了解可以查閱HTML格式的Java文檔。異常的基本概念是用名稱代表發(fā)生的問題,即可以望文知意。但需要指出的是,異常并非全是在java.lang包里定義的。有些異常是用來支持其他的程序包,如util、net和io,這些異??梢酝ㄟ^完整的名稱或者從其父類中看出,比如所有的輸出/輸出異常都是從java.io.IOException繼承而來的。同時,Java中異常的數(shù)目在持續(xù)增加,所使用的第三方類庫也可能會有自己的異常。所以對于異常,關(guān)鍵是理解概念以及了解如何使用。
Java異常處理主要通過5個關(guān)鍵字控制:try、catch、throw、throws和finally。try的意思是試一試它所包含的代碼段中是否會發(fā)生異常;當(dāng)有異常時,用catch抓住它,并進(jìn)行相應(yīng)的處理,使程序不受該異常的影響繼續(xù)執(zhí)行下去;在程序中用throw明確引發(fā)異常;throws的作用是如果一個方法可以引發(fā)異常,而它本身并不對該異常處理,那么它必須將這個異常拋給調(diào)用它的方法;finally是無論發(fā)不發(fā)生異常都要被執(zhí)行的代碼。5.2異常處理5.2.1try/catch語句
1.try塊
對于異常處理,Java語言提供默認(rèn)的處理方式。但使用此方式,一旦程序發(fā)生異常,程序就會終止運(yùn)行并顯示一些信息,這樣用戶界面就不很友好。為了避免程序運(yùn)行時可能出現(xiàn)的錯誤,將這些程序代碼放在try塊中,在這個塊里“嘗試”各種(可能產(chǎn)生異常的)方法調(diào)用,用來捕獲異常,所以稱其為try塊。try塊是跟在try關(guān)鍵字之后的普通程序塊:
try{
//可能拋出異常的代碼
}
2.catch塊
當(dāng)然,拋出的異常必須在某處得到處理。這個“某處”就是“異常處理程序”,而且針對每個要捕獲的異常,得準(zhǔn)備相應(yīng)的處理程序。所以,緊跟在try語句后面設(shè)計(jì)了catch語句,用來指定需要捕捉的異常類型,形式如下:
try{
//可能拋出異常的代碼
}catch(Type1id1){//處理捕獲的第一類異常
}catch(Type2id2){
//處理捕獲的第二類異常
}catch(Type3id3){
//處理捕獲的第三類異常
}
//等等
catch子句(異常處理程序)就像是只接受一個特殊類型的參數(shù)的方法。異常處理程序必須緊跟在try塊之后,一旦出現(xiàn)異常情況,程序拋出一個異常并終止try程序的運(yùn)行,異常處理機(jī)制將負(fù)責(zé)搜尋參數(shù)與異常類型相匹配的第一個處理程序。然后進(jìn)入catch子句執(zhí)行,此時認(rèn)為異常得到了處理。一旦catch子句結(jié)束,則處理程序的查找過程結(jié)束。需要注意的是,只有匹配的catch子句才能得到執(zhí)行。
現(xiàn)在針對DivideZero.java程序做幾種處理,分析運(yùn)行結(jié)果,深入理解try/catch的處理機(jī)制。【例5-2】沒有cathch語句的程序。
publicclassDivideZero_Handle1{
intx;
publicstaticvoidmain(String[]args){
intresult;
DivideZero_Handle1k=newDivideZero_Handle1();try{
result=35/k.x;
System.out.println("result="+result);
}
System.out.println("programendsok!");
}
}
程序編譯結(jié)果如圖5-2所示。圖5-2DivideZero_Handle1.java的編譯結(jié)果【例5-3】只有一條cathch語句的程序。
publicclassDivideZero_Handle2{
intx;
publicstaticvoidmain(String[]args){
intresult;
DivideZero_Handle2k=newDivideZero_Handle2();
try{
result=35/k.x;System.out.println("result="+result);
}
catch(Exceptione){//捕獲異常
System.out.println("errorsoccur!");
}
System.out.println("programendsok!");
}
}
程序運(yùn)行結(jié)果如圖5-3所示。圖5-3DivideZero_Handle2.java的運(yùn)行結(jié)果【例5-4】顯示異常類對象的相關(guān)信息。
publicclassDivideZero_Handle3{
intx;
publicstaticvoidmain(String[]args){
intresult;
DivideZero_Handle3k=newDivideZero_Handle3();
try{
result=35/k.x;
System.out.println("result="+result);
}
catch(Exceptione){//將堆棧軌跡輸出到標(biāo)準(zhǔn)錯誤流
e.printStackTrace();
//得到這個對象的錯誤消息字符串
System.out.println("getmessage="+e.getMessage());
//得到這個對象的短說明
System.out.println("tostring="+e.toString());
}
System.out.println("programendsok!");
}
}
程序運(yùn)行結(jié)果如圖5-4所示。圖5-4DivideZero_Handle3.java的運(yùn)行結(jié)果
catch的參數(shù)e為Exception類型,它繼承了Throwable類。該類中有多個方法可以得到對象e的異常信息。
【例5-5】有多條catch語句的程序。
publicclassDivideZero_Handle4{
intx;
publicstaticvoidmain(String[]args){
intresult;
DivideZero_Handle4k=newDivideZero_Handle4();
try{result=35/k.x;
System.out.println("result="+result);
}
catch(ArrayStoreExceptione){//第1條catch語句
System.out.println("數(shù)組下標(biāo)越界.");
}
catch(ArithmeticExceptione){//第2條catch語句
System.out.println("出現(xiàn)被0除的異常情況.");}
catch(Exceptione){//第3條catch語句
System.out.println("檢查除數(shù)的有效性.");
}
System.out.println("programendsok!");
}
}
程序運(yùn)行結(jié)果如圖5-5所示。圖5-5DivideZero_Handle4.java的運(yùn)行結(jié)果異常處理機(jī)制從多個catch子句中搜尋到參數(shù)與異常類型(ArithmeticException)相匹配的第一個處理程序,然后進(jìn)入catch子句執(zhí)行處理程序,處理完后,跳出try/catch塊,繼續(xù)執(zhí)行程序。
實(shí)際上ArithmeticException異常類是Exception類的子類,如果將第二個catch語句屏蔽掉,異常處理機(jī)制就會順次找到第三個catch子句并執(zhí)行,情況與例5-4相同。程序運(yùn)行結(jié)果如圖5-6所示。圖5-6屏蔽了第二個catch子句后的運(yùn)行結(jié)果5.2.2throw/throws語句
1.throw語句
如果在執(zhí)行一段代碼時,需要程序進(jìn)行其他處理,就可以借助于異常,使程序執(zhí)行指定的操作。產(chǎn)生異常又稱為拋出異常,如果要故意拋出ClassCastException異常(類強(qiáng)制轉(zhuǎn)換異常),那么可以在try中增加下面的語句:
thrownewClassCastException();關(guān)鍵字throw的意思就是“拋出”,newClassCastException()就是創(chuàng)建了一個ClassCastException類的對象。
下面這個程序用來計(jì)算一個非負(fù)整數(shù)的平方根。
【例5-6】ThrowDemo.java程序。
publicclassThrowDemo{
intx;
publicThrowDemo(inttemp){
x=temp;
}
publicstaticvoidmain(String[]args){
ThrowDemok=newThrowDemo(-15);
try{
if(k.x<0)
thrownewException("需要計(jì)算的數(shù)必須是一個非負(fù)整數(shù)!");
else
System.out.println("sqrt("+k.x+")="+Math.sqrt(k.x));}
catch(Exceptione){
System.out.println("GotaException:"+e.getMessage());
}
}
}
程序運(yùn)行結(jié)果如圖5-7所示。圖5-7ThrowDemo.java的運(yùn)行結(jié)果
2.throws語句
在ThrowDemo.java程序中,異常拋出后,是在異常被拋出的方法(main方法)中進(jìn)行處理的。如果拋出的異常由調(diào)用它的方法完成處理該如何做?這時需要把異常從產(chǎn)生異常的方法中拋出,即利用throws關(guān)鍵字進(jìn)行處理。假設(shè)將平方根的計(jì)算用sqrt方法進(jìn)行設(shè)計(jì),把異常從方法中拋出的程序是:
publicvoidsqrt()throwsException{
//求平方根的程序代碼
}
在方法的聲明中加上throwsException,就可以把sqrt方法中產(chǎn)生的異常拋出方法之外,留給調(diào)用它的其他方法(main方法)去處理。【例5-7】利用throws語句處理ThrowDemo.java程序。
publicclassThrowsDemo_1{
intx;
publicThrowsDemo_1(inttemp){
x=temp;
}
publicvoidsqrt()throwsException{//方法聲明中拋出可能出現(xiàn)的異常
if(x<0)
thrownewException("需要計(jì)算的數(shù)必須是一個非負(fù)整數(shù)!");
elseSystem.out.println("sqrt("+x+")="+Math.sqrt(x));
}
publicstaticvoidmain(String[]args){
ThrowsDemo_1k=newThrowsDemo_1(-15);
try{
k.sqrt();}
catch(Exceptione){
System.out.println("Caughtinsidemain_method:"+e.getMessage());
}
}
}
程序運(yùn)行結(jié)果如圖5-8所示。圖5-8ThrowsDemo_1.java的運(yùn)行結(jié)果為了更好地理解throw和throws的用法,請閱讀和分析下面這個例題。
【例5-8】利用throw和throws語句進(jìn)行非負(fù)整數(shù)的平方根計(jì)算。
publicclassThrowsDemo_2{
intx;
publicThrowsDemo_2(inttemp){
x=temp;
}
publicvoidsqrt()throwsException{
try{
if(x<0)
thrownewException("需要計(jì)算的數(shù)必須是一個非負(fù)整數(shù)!");
else
System.out.println("sqrt("+x+")="+Math.sqrt(x));
}
catch(Exceptione){//捕獲try語句中拋出的異常System.out.println("Caughtinsidesqrt_method:"+e.getMessage());
throwe;//拋出異常對象e,交給上一級方法—main
}
}
publicstaticvoidmain(String[]args){
ThrowsDemo_2k=newThrowsDemo_2(-15);
try{k.sqrt();
}
catch(Exceptione){//捕獲sqrt方法拋出的異常
System.out.println("Caughtinsidemain_method:"+e.getMessage());
}
}
}
程序運(yùn)行結(jié)果如圖5-9所示。圖5-9ThrowsDemo_2.java的運(yùn)行結(jié)果通過這個例題的演示,throw和throws的概念更加明顯:
(1)?throw出現(xiàn)在方法體中,用于拋出異常。當(dāng)方法在執(zhí)行過程中遇到異常情況時,程序?qū)惓P畔⒎庋b為異常對象,然后throw。
(2)?throws出現(xiàn)在方法的聲明中,表示該方法可能會拋出的異常,允許throws后面跟著多個異常類型。5.2.3finally語句
如果希望無論try塊中的異常是否拋出,程序都能執(zhí)行一段代碼,Java提供了另一種處理塊的語法,即finally關(guān)鍵字。
finally語句創(chuàng)建一個代碼塊,在try/catch語句后執(zhí)行,不管是否拋出異常,系統(tǒng)都將執(zhí)行finally語句的程序代碼。所以完整的異常處理應(yīng)該如下面的形式:
try{
//可能拋出異常A、BorC
}catch(Aa1{//處理異常情況A
}catch(Bb1){
//處理異常情況B
}catch(Cc1){
//處理異常情況C
}finally{
//任何情況都必須執(zhí)行的代碼
}
【例5-9】程序FinallyTest.java對finally的使用情況作了測試。
publicclassFinallyTest{
intx;
publicFinallyTest(inttemp){
x=temp;
}publicstaticvoidmain(String[]args){
FinallyTestk=newFinallyTest(-15);
try{
if(k.x<0)
thrownewException("需要計(jì)算的數(shù)必須是一個非負(fù)整數(shù)!");
else
System.out.println("sqrt("+k.x+")="+Math.sqrt(k.x));
}catch(Exceptione){
System.out.println("GotaException:"+e.getMessage());
}
finally{
System.out.println("被求平方根的數(shù)是:"+k.x);
}
}
}
程序運(yùn)行結(jié)果如圖5-10所示。圖5-10FinallyTest.java的運(yùn)行結(jié)果如果將-15改成16,程序的運(yùn)行結(jié)果如圖5-11所示。
從兩個輸出結(jié)果中發(fā)現(xiàn),無論異常是否被拋出,finally子句總能被執(zhí)行。使用finally語句可為異常處理提供統(tǒng)一的出口,一般來說可以在finally語句中進(jìn)行資源清除工作,如關(guān)閉已打開的文件等。圖5-11對16求平方根的運(yùn)行結(jié)果5.2.4自定義異常
Java提供的異常體系不可能預(yù)見所有可能出現(xiàn)的錯誤。在實(shí)際應(yīng)用中,可以自己定義異常類來表示程序中可能會遇到的特定問題。
如果要建立自己的異常類,必須從已有的異常類繼承。根據(jù)前面的知識,異常處理類的頂層類是Throwable,但是Java程序員關(guān)心的基類型通常是它的子類Exception。所以可以通過繼承Exception類來創(chuàng)建自己的異常類,即只需提供一個構(gòu)造方法并覆蓋要使用的方法即可。表5-1列出了Throwable類的構(gòu)造函數(shù)。表5-1Throwable類的構(gòu)造函數(shù)下面建立的是一個最簡單的異常類:
classSimpleExceptionextendsException{}
這個異常類讓編譯器產(chǎn)生了缺省的構(gòu)造方法,它將自動調(diào)用基類的缺省構(gòu)造器。
【例5-10】創(chuàng)建自定義異常類,完成輸入溫度的檢測報告。如果溫度高于75度,顯示不正常,否則均為正常。
classNewExceptionextendsException{
//創(chuàng)建自定義異常類
intvalue;
//帶參數(shù)的構(gòu)造方法的定義
NewException(inttemp){
value=temp;
}
publicStringtoString(){
//覆蓋了父類方法toString(),使對象具有自己的顯示信息
return"NewException"+value+"度";}
}
publicclassTemperatureForecast{
staticvoidforecast(intvalue)throwsNewException{
//溫度檢測
if(value>75)
thrownewNewException(value);
else
System.out.println(value+"度:Noproblem.");
}publicstaticvoidmain(String[]args){
try{//檢測三個溫度
forecast(60);
forecast(55);
forecast(95);
}
catch(NewExceptione){//處理forecast方法中拋出的異常
System.out.println(e+":HigherTemperature!");
}
}
}
程序運(yùn)行結(jié)果如圖5-12所示。圖5-12TemperatureForecast.java的運(yùn)行結(jié)果
【例5-11】創(chuàng)建自定義異常類,完成對銀行賬目的操作處理。
類BankAccount維持銀行賬目的余額:
(1)它有兩個構(gòu)造方法:①用空的余額創(chuàng)建一個新的銀行賬戶;②用正的余額創(chuàng)建一個新的銀行賬戶;
(2)提供三個實(shí)例方法支持余額的訪問和操作:①返回該銀行賬戶的余額;②向該銀行賬戶中存入正值的數(shù)額;③從該銀行賬戶中取出正值的數(shù)額。程序清單如下:
//創(chuàng)建自定義異常類,表示一個不正常的銀行賬目事件
classNegativeAmountExceptionextendsException{
//用消息s創(chuàng)建異常
publicNegativeAmountException(Strings){
super(s); //調(diào)用基類構(gòu)造器,接受一個字符串作為參數(shù)
}
}//表示銀行賬目余額
classBankAccount{
intbalance;
//默認(rèn)的構(gòu)造方法,余額為空
publicBankAccount(){
balance=0;
}//特定的構(gòu)造方法,余額為n
publicBankAccount(intn)throwsNegativeAmountException{
if(n>=0)
balance=n;
else
thrownewNegativeAmountException("Badbalance.");
}//返回當(dāng)前的余額
publicintgetBanlance(){
returnbalance;
}
//存款:數(shù)額為n
publicvoidaddFunds(intn)throwsNegativeAmountException{
if(n>=0)
balance+=n;
elsethrownewNegativeAmountException("Badbalance.");
}
//取款:數(shù)額為n
publicvoidremoveFunds(intn)throwsNegativeAmountException{
if(n<0)
thrownewNegativeAmountException("Badbalance.");
elseif(balance<n)
thrownewNegativeAmountException("Badbalance.");
else
balance-=n;}
}
//進(jìn)行業(yè)務(wù)操作
publicclassDeposits{
publicstaticvoidmain(String[]args){
try{
BankAccountk1=newBankAccount(500);
//向k1里存500
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 肛瘺護(hù)理課件
- 對口統(tǒng)招數(shù)學(xué)試卷
- 對口本科數(shù)學(xué)試卷
- 東營高考一模數(shù)學(xué)試卷
- 玻璃維修培訓(xùn)課件大全
- 2025至2030磁引導(dǎo)膠囊內(nèi)鏡行業(yè)市場深度研究與戰(zhàn)略咨詢分析報告
- 2024年汕尾市市直單位招聘政府聘員筆試真題
- 2024年撫順職業(yè)技術(shù)學(xué)院輔導(dǎo)員考試真題
- 2025至2030餐飲行業(yè)市場深度研究及發(fā)展前景投資可行性分析報告
- 高二基礎(chǔ)數(shù)學(xué)試卷
- 獸醫(yī)傳染病學(xué)(山東聯(lián)盟)智慧樹知到答案章節(jié)測試2023年青島農(nóng)業(yè)大學(xué)
- 鋼結(jié)構(gòu)防腐油漆施工方案
- 第五講社會建設(shè)
- GB/T 35273-2020信息安全技術(shù)個人信息安全規(guī)范
- GB/T 20303.1-2006起重機(jī)司機(jī)室第1部分:總則
- GB 18068-2000水泥廠衛(wèi)生防護(hù)距離標(biāo)準(zhǔn)
- 教師調(diào)動登記表(模板)
- 《長方形和正方形》 完整版課件
- 2022年醫(yī)院收費(fèi)員考試試題及答案
- 國家開放大學(xué)電大??啤妒袌鰻I銷學(xué)》2021期末試題及答案(試卷號2175)
- 再遇青春同學(xué)聚會畫冊PPT模板
評論
0/150
提交評論