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

下載本文檔

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

文檔簡(jiǎn)介

5.1異常分析及異常類

5.2異常處理

5.3小結(jié)

5.4習(xí)題

5.1.1一個(gè)有問題的程序

什么是異常?先來分析一個(gè)程序及其運(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é)果這個(gè)程序在編譯時(shí)不會(huì)出現(xiàn)問題,但是在運(yùn)行時(shí)出現(xiàn)了異常。通過提示信息可以知道,程序中第6行的位置出現(xiàn)了被0除的情況。再仔細(xì)考慮一下,原來在創(chuàng)建對(duì)象k的時(shí)候,其數(shù)據(jù)成員x被初始化成0,即k.x為0,而除0是非法的。

當(dāng)程序運(yùn)行時(shí),會(huì)發(fā)生不正常的事件阻止事先設(shè)計(jì)好的程序的執(zhí)行,這些事件稱為異常。當(dāng)這個(gè)程序運(yùn)行到“35/k.x”時(shí),Java拋出一個(gè)異常,該異常表示算術(shù)操作不能執(zhí)行,并且程序自動(dòng)終止。Java拋出的這個(gè)異常為java.lang.ArithmeticException,是一個(gè)類。為什么運(yùn)行結(jié)果有錯(cuò)誤信息的提示呢?這與Java處理異常的機(jī)制有關(guān)。當(dāng)Java拋出異常后,有幾件事會(huì)隨之發(fā)生。首先,同Java中其他對(duì)象的創(chuàng)建一樣,Java將使用new創(chuàng)建異常對(duì)象。然后,由于當(dāng)前的執(zhí)行路徑不能繼續(xù)下去了,所以該路徑被終止,并且彈出對(duì)異常對(duì)象的引用。此時(shí),異常處理機(jī)制接管程序,并開始尋找一個(gè)恰當(dāng)?shù)牡胤絹砝^續(xù)執(zhí)行程序。這個(gè)恰當(dāng)?shù)牡胤骄褪恰爱惓L幚沓绦颉保娜蝿?wù)是將程序從錯(cuò)誤狀態(tài)中恢復(fù),以使程序要么換一種方式運(yùn)行,要么以原有方式繼續(xù)運(yùn)行下去。5.1.2異常類的組織

用面向?qū)ο蟮姆椒▉磉M(jìn)行異常處理,首先必須建立異常處理類的層次。在異常處理類層次的最上層有一個(gè)單獨(dú)的類叫做Throwable類,用來表示任何可以作為異常被拋出的類,每個(gè)異常類都是Throwable的子類。異常類的層次關(guān)系如下:

Throwable對(duì)象可分為兩種類型(從Throwable繼承而得到的類型):Error用來表示編譯和系統(tǒng)錯(cuò)誤(除特殊情況外,一般不用程序員關(guān)心);Exception是可以被拋出的基本類型,在Java類庫(kù)、用戶方法以及運(yùn)行故障中都可能拋出Exception型異常。所以Java程序員關(guān)心的基類型通常是Exception。對(duì)于Java異常類的全面了解可以查閱HTML格式的Java文檔。異常的基本概念是用名稱代表發(fā)生的問題,即可以望文知意。但需要指出的是,異常并非全是在java.lang包里定義的。有些異常是用來支持其他的程序包,如util、net和io,這些異??梢酝ㄟ^完整的名稱或者從其父類中看出,比如所有的輸出/輸出異常都是從java.io.IOException繼承而來的。同時(shí),Java中異常的數(shù)目在持續(xù)增加,所使用的第三方類庫(kù)也可能會(huì)有自己的異常。所以對(duì)于異常,關(guān)鍵是理解概念以及了解如何使用。

Java異常處理主要通過5個(gè)關(guān)鍵字控制:try、catch、throw、throws和finally。try的意思是試一試它所包含的代碼段中是否會(huì)發(fā)生異常;當(dāng)有異常時(shí),用catch抓住它,并進(jìn)行相應(yīng)的處理,使程序不受該異常的影響繼續(xù)執(zhí)行下去;在程序中用throw明確引發(fā)異常;throws的作用是如果一個(gè)方法可以引發(fā)異常,而它本身并不對(duì)該異常處理,那么它必須將這個(gè)異常拋給調(diào)用它的方法;finally是無論發(fā)不發(fā)生異常都要被執(zhí)行的代碼。5.2異常處理5.2.1try/catch語(yǔ)句

1.try塊

對(duì)于異常處理,Java語(yǔ)言提供默認(rèn)的處理方式。但使用此方式,一旦程序發(fā)生異常,程序就會(huì)終止運(yùn)行并顯示一些信息,這樣用戶界面就不很友好。為了避免程序運(yùn)行時(shí)可能出現(xiàn)的錯(cuò)誤,將這些程序代碼放在try塊中,在這個(gè)塊里“嘗試”各種(可能產(chǎn)生異常的)方法調(diào)用,用來捕獲異常,所以稱其為try塊。try塊是跟在try關(guān)鍵字之后的普通程序塊:

try{

//可能拋出異常的代碼

}

2.catch塊

當(dāng)然,拋出的異常必須在某處得到處理。這個(gè)“某處”就是“異常處理程序”,而且針對(duì)每個(gè)要捕獲的異常,得準(zhǔn)備相應(yīng)的處理程序。所以,緊跟在try語(yǔ)句后面設(shè)計(jì)了catch語(yǔ)句,用來指定需要捕捉的異常類型,形式如下:

try{

//可能拋出異常的代碼

}catch(Type1id1){//處理捕獲的第一類異常

}catch(Type2id2){

//處理捕獲的第二類異常

}catch(Type3id3){

//處理捕獲的第三類異常

}

//等等

catch子句(異常處理程序)就像是只接受一個(gè)特殊類型的參數(shù)的方法。異常處理程序必須緊跟在try塊之后,一旦出現(xiàn)異常情況,程序拋出一個(gè)異常并終止try程序的運(yùn)行,異常處理機(jī)制將負(fù)責(zé)搜尋參數(shù)與異常類型相匹配的第一個(gè)處理程序。然后進(jìn)入catch子句執(zhí)行,此時(shí)認(rèn)為異常得到了處理。一旦catch子句結(jié)束,則處理程序的查找過程結(jié)束。需要注意的是,只有匹配的catch子句才能得到執(zhí)行。

現(xiàn)在針對(duì)DivideZero.java程序做幾種處理,分析運(yùn)行結(jié)果,深入理解try/catch的處理機(jī)制。【例5-2】沒有cathch語(yǔ)句的程序。

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語(yǔ)句的程序。

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】顯示異常類對(duì)象的相關(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)錯(cuò)誤流

e.printStackTrace();

//得到這個(gè)對(duì)象的錯(cuò)誤消息字符串

System.out.println("getmessage="+e.getMessage());

//得到這個(gè)對(duì)象的短說明

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類。該類中有多個(gè)方法可以得到對(duì)象e的異常信息。

【例5-5】有多條catch語(yǔ)句的程序。

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語(yǔ)句

System.out.println("數(shù)組下標(biāo)越界.");

}

catch(ArithmeticExceptione){//第2條catch語(yǔ)句

System.out.println("出現(xiàn)被0除的異常情況.");}

catch(Exceptione){//第3條catch語(yǔ)句

System.out.println("檢查除數(shù)的有效性.");

}

System.out.println("programendsok!");

}

}

程序運(yùn)行結(jié)果如圖5-5所示。圖5-5DivideZero_Handle4.java的運(yùn)行結(jié)果異常處理機(jī)制從多個(gè)catch子句中搜尋到參數(shù)與異常類型(ArithmeticException)相匹配的第一個(gè)處理程序,然后進(jìn)入catch子句執(zhí)行處理程序,處理完后,跳出try/catch塊,繼續(xù)執(zhí)行程序。

實(shí)際上ArithmeticException異常類是Exception類的子類,如果將第二個(gè)catch語(yǔ)句屏蔽掉,異常處理機(jī)制就會(huì)順次找到第三個(gè)catch子句并執(zhí)行,情況與例5-4相同。程序運(yùn)行結(jié)果如圖5-6所示。圖5-6屏蔽了第二個(gè)catch子句后的運(yùn)行結(jié)果5.2.2throw/throws語(yǔ)句

1.throw語(yǔ)句

如果在執(zhí)行一段代碼時(shí),需要程序進(jìn)行其他處理,就可以借助于異常,使程序執(zhí)行指定的操作。產(chǎn)生異常又稱為拋出異常,如果要故意拋出ClassCastException異常(類強(qiáng)制轉(zhuǎn)換異常),那么可以在try中增加下面的語(yǔ)句:

thrownewClassCastException();關(guān)鍵字throw的意思就是“拋出”,newClassCastException()就是創(chuàng)建了一個(gè)ClassCastException類的對(duì)象。

下面這個(gè)程序用來計(jì)算一個(gè)非負(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ù)必須是一個(gè)非負(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語(yǔ)句

在ThrowDemo.java程序中,異常拋出后,是在異常被拋出的方法(main方法)中進(jìn)行處理的。如果拋出的異常由調(diào)用它的方法完成處理該如何做?這時(shí)需要把異常從產(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語(yǔ)句處理ThrowDemo.java程序。

publicclassThrowsDemo_1{

intx;

publicThrowsDemo_1(inttemp){

x=temp;

}

publicvoidsqrt()throwsException{//方法聲明中拋出可能出現(xiàn)的異常

if(x<0)

thrownewException("需要計(jì)算的數(shù)必須是一個(gè)非負(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的用法,請(qǐng)閱讀和分析下面這個(gè)例題。

【例5-8】利用throw和throws語(yǔ)句進(jìn)行非負(fù)整數(shù)的平方根計(jì)算。

publicclassThrowsDemo_2{

intx;

publicThrowsDemo_2(inttemp){

x=temp;

}

publicvoidsqrt()throwsException{

try{

if(x<0)

thrownewException("需要計(jì)算的數(shù)必須是一個(gè)非負(fù)整數(shù)!");

else

System.out.println("sqrt("+x+")="+Math.sqrt(x));

}

catch(Exceptione){//捕獲try語(yǔ)句中拋出的異常System.out.println("Caughtinsidesqrt_method:"+e.getMessage());

throwe;//拋出異常對(duì)象e,交給上一級(jí)方法—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é)果通過這個(gè)例題的演示,throw和throws的概念更加明顯:

(1)?throw出現(xiàn)在方法體中,用于拋出異常。當(dāng)方法在執(zhí)行過程中遇到異常情況時(shí),程序?qū)惓P畔⒎庋b為異常對(duì)象,然后throw。

(2)?throws出現(xiàn)在方法的聲明中,表示該方法可能會(huì)拋出的異常,允許throws后面跟著多個(gè)異常類型。5.2.3finally語(yǔ)句

如果希望無論try塊中的異常是否拋出,程序都能執(zhí)行一段代碼,Java提供了另一種處理塊的語(yǔ)法,即finally關(guān)鍵字。

finally語(yǔ)句創(chuàng)建一個(gè)代碼塊,在try/catch語(yǔ)句后執(zhí)行,不管是否拋出異常,系統(tǒng)都將執(zhí)行finally語(yǔ)句的程序代碼。所以完整的異常處理應(yīng)該如下面的形式:

try{

//可能拋出異常A、BorC

}catch(Aa1{//處理異常情況A

}catch(Bb1){

//處理異常情況B

}catch(Cc1){

//處理異常情況C

}finally{

//任何情況都必須執(zhí)行的代碼

}

【例5-9】程序FinallyTest.java對(duì)finally的使用情況作了測(cè)試。

publicclassFinallyTest{

intx;

publicFinallyTest(inttemp){

x=temp;

}publicstaticvoidmain(String[]args){

FinallyTestk=newFinallyTest(-15);

try{

if(k.x<0)

thrownewException("需要計(jì)算的數(shù)必須是一個(gè)非負(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所示。

從兩個(gè)輸出結(jié)果中發(fā)現(xiàn),無論異常是否被拋出,finally子句總能被執(zhí)行。使用finally語(yǔ)句可為異常處理提供統(tǒng)一的出口,一般來說可以在finally語(yǔ)句中進(jìn)行資源清除工作,如關(guān)閉已打開的文件等。圖5-11對(duì)16求平方根的運(yùn)行結(jié)果5.2.4自定義異常

Java提供的異常體系不可能預(yù)見所有可能出現(xiàn)的錯(cuò)誤。在實(shí)際應(yīng)用中,可以自己定義異常類來表示程序中可能會(huì)遇到的特定問題。

如果要建立自己的異常類,必須從已有的異常類繼承。根據(jù)前面的知識(shí),異常處理類的頂層類是Throwable,但是Java程序員關(guān)心的基類型通常是它的子類Exception。所以可以通過繼承Exception類來創(chuàng)建自己的異常類,即只需提供一個(gè)構(gòu)造方法并覆蓋要使用的方法即可。表5-1列出了Throwable類的構(gòu)造函數(shù)。表5-1Throwable類的構(gòu)造函數(shù)下面建立的是一個(gè)最簡(jiǎn)單的異常類:

classSimpleExceptionextendsException{}

這個(gè)異常類讓編譯器產(chǎn)生了缺省的構(gòu)造方法,它將自動(dòng)調(diào)用基類的缺省構(gòu)造器。

【例5-10】創(chuàng)建自定義異常類,完成輸入溫度的檢測(cè)報(bào)告。如果溫度高于75度,顯示不正常,否則均為正常。

classNewExceptionextendsException{

//創(chuàng)建自定義異常類

intvalue;

//帶參數(shù)的構(gòu)造方法的定義

NewException(inttemp){

value=temp;

}

publicStringtoString(){

//覆蓋了父類方法toString(),使對(duì)象具有自己的顯示信息

return"NewException"+value+"度";}

}

publicclassTemperatureForecast{

staticvoidforecast(intvalue)throwsNewException{

//溫度檢測(cè)

if(value>75)

thrownewNewException(value);

else

System.out.println(value+"度:Noproblem.");

}publicstaticvoidmain(String[]args){

try{//檢測(cè)三個(gè)溫度

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)建自定義異常類,完成對(duì)銀行賬目的操作處理。

類BankAccount維持銀行賬目的余額:

(1)它有兩個(gè)構(gòu)造方法:①用空的余額創(chuàng)建一個(gè)新的銀行賬戶;②用正的余額創(chuàng)建一個(gè)新的銀行賬戶;

(2)提供三個(gè)實(shí)例方法支持余額的訪問和操作:①返回該銀行賬戶的余額;②向該銀行賬戶中存入正值的數(shù)額;③從該銀行賬戶中取出正值的數(shù)額。程序清單如下:

//創(chuàng)建自定義異常類,表示一個(gè)不正常的銀行賬目事件

classNegativeAmountExceptionextendsException{

//用消息s創(chuàng)建異常

publicNegativeAmountException(Strings){

super(s); //調(diào)用基類構(gòu)造器,接受一個(gè)字符串作為參數(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等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 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)論