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

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

5.1異常分析及異常類

5.2異常處理

5.3小結

5.4習題

5.1.1一個有問題的程序

什么是異常?先來分析一個程序及其運行結果。

【例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");

}

}

程序運行結果如圖5-1所示。圖5-1DivideZero.java的運行結果這個程序在編譯時不會出現(xiàn)問題,但是在運行時出現(xiàn)了異常。通過提示信息可以知道,程序中第6行的位置出現(xiàn)了被0除的情況。再仔細考慮一下,原來在創(chuàng)建對象k的時候,其數(shù)據(jù)成員x被初始化成0,即k.x為0,而除0是非法的。

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

用面向對象的方法來進行異常處理,首先必須建立異常處理類的層次。在異常處理類層次的最上層有一個單獨的類叫做Throwable類,用來表示任何可以作為異常被拋出的類,每個異常類都是Throwable的子類。異常類的層次關系如下:

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

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

1.try塊

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

try{

//可能拋出異常的代碼

}

2.catch塊

當然,拋出的異常必須在某處得到處理。這個“某處”就是“異常處理程序”,而且針對每個要捕獲的異常,得準備相應的處理程序。所以,緊跟在try語句后面設計了catch語句,用來指定需要捕捉的異常類型,形式如下:

try{

//可能拋出異常的代碼

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

}catch(Type2id2){

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

}catch(Type3id3){

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

}

//等等

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

現(xiàn)在針對DivideZero.java程序做幾種處理,分析運行結果,深入理解try/catch的處理機制。【例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!");

}

}

程序編譯結果如圖5-2所示。圖5-2DivideZero_Handle1.java的編譯結果【例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!");

}

}

程序運行結果如圖5-3所示。圖5-3DivideZero_Handle2.java的運行結果【例5-4】顯示異常類對象的相關信息。

publicclassDivideZero_Handle3{

intx;

publicstaticvoidmain(String[]args){

intresult;

DivideZero_Handle3k=newDivideZero_Handle3();

try{

result=35/k.x;

System.out.println("result="+result);

}

catch(Exceptione){//將堆棧軌跡輸出到標準錯誤流

e.printStackTrace();

//得到這個對象的錯誤消息字符串

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

//得到這個對象的短說明

System.out.println("tostring="+e.toString());

}

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

}

}

程序運行結果如圖5-4所示。圖5-4DivideZero_Handle3.java的運行結果

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ù)組下標越界.");

}

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

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

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

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

}

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

}

}

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

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

1.throw語句

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

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

下面這個程序用來計算一個非負整數(shù)的平方根。

【例5-6】ThrowDemo.java程序。

publicclassThrowDemo{

intx;

publicThrowDemo(inttemp){

x=temp;

}

publicstaticvoidmain(String[]args){

ThrowDemok=newThrowDemo(-15);

try{

if(k.x<0)

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

else

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

catch(Exceptione){

System.out.println("GotaException:"+e.getMessage());

}

}

}

程序運行結果如圖5-7所示。圖5-7ThrowDemo.java的運行結果

2.throws語句

在ThrowDemo.java程序中,異常拋出后,是在異常被拋出的方法(main方法)中進行處理的。如果拋出的異常由調用它的方法完成處理該如何做?這時需要把異常從產生異常的方法中拋出,即利用throws關鍵字進行處理。假設將平方根的計算用sqrt方法進行設計,把異常從方法中拋出的程序是:

publicvoidsqrt()throwsException{

//求平方根的程序代碼

}

在方法的聲明中加上throwsException,就可以把sqrt方法中產生的異常拋出方法之外,留給調用它的其他方法(main方法)去處理?!纠?-7】利用throws語句處理ThrowDemo.java程序。

publicclassThrowsDemo_1{

intx;

publicThrowsDemo_1(inttemp){

x=temp;

}

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

if(x<0)

thrownewException("需要計算的數(shù)必須是一個非負整數(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());

}

}

}

程序運行結果如圖5-8所示。圖5-8ThrowsDemo_1.java的運行結果為了更好地理解throw和throws的用法,請閱讀和分析下面這個例題。

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

publicclassThrowsDemo_2{

intx;

publicThrowsDemo_2(inttemp){

x=temp;

}

publicvoidsqrt()throwsException{

try{

if(x<0)

thrownewException("需要計算的數(shù)必須是一個非負整數(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());

}

}

}

程序運行結果如圖5-9所示。圖5-9ThrowsDemo_2.java的運行結果通過這個例題的演示,throw和throws的概念更加明顯:

(1)?throw出現(xiàn)在方法體中,用于拋出異常。當方法在執(zhí)行過程中遇到異常情況時,程序將異常信息封裝為異常對象,然后throw。

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

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

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

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("需要計算的數(shù)必須是一個非負整數(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);

}

}

}

程序運行結果如圖5-10所示。圖5-10FinallyTest.java的運行結果如果將-15改成16,程序的運行結果如圖5-11所示。

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

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

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

classSimpleExceptionextendsException{}

這個異常類讓編譯器產生了缺省的構造方法,它將自動調用基類的缺省構造器。

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

classNewExceptionextendsException{

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

intvalue;

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

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!");

}

}

}

程序運行結果如圖5-12所示。圖5-12TemperatureForecast.java的運行結果

【例5-11】創(chuàng)建自定義異常類,完成對銀行賬目的操作處理。

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

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

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

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

classNegativeAmountExceptionextendsException{

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

publicNegativeAmountException(Strings){

super(s); //調用基類構造器,接受一個字符串作為參數(shù)

}

}//表示銀行賬目余額

classBankAccount{

intbalance;

//默認的構造方法,余額為空

publicBankAccount(){

balance=0;

}//特定的構造方法,余額為n

publicBankAccount(intn)throwsNegativeAmountException{

if(n>=0)

balance=n;

else

thrownewNegativeAmountException("Badbalance.");

}//返回當前的余額

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;}

}

//進行業(yè)務操作

publicclassDeposits{

publicstaticvoidmain(String[]args){

try{

BankAccountk1=newBankAccount(500);

//向k1里存500

溫馨提示

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

評論

0/150

提交評論