JAVA 第六章 異常處理_第1頁(yè)
JAVA 第六章 異常處理_第2頁(yè)
JAVA 第六章 異常處理_第3頁(yè)
JAVA 第六章 異常處理_第4頁(yè)
JAVA 第六章 異常處理_第5頁(yè)
已閱讀5頁(yè),還剩114頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

第6章異常處理6.1程序錯(cuò)誤與處理6.2Java的異常處理6.3自定義異常類(lèi)6.4編程實(shí)例 6.1程序錯(cuò)誤與處理程序中的錯(cuò)誤有不同的性質(zhì),不同的錯(cuò)誤需要采用不同的處理方式。按照錯(cuò)誤的性質(zhì)可將程序錯(cuò)誤分成3類(lèi):語(yǔ)法錯(cuò)、語(yǔ)義錯(cuò)、邏輯錯(cuò)。6.1.1程序錯(cuò)誤、發(fā)現(xiàn)時(shí)刻及錯(cuò)誤處理原則1.語(yǔ)法錯(cuò)違反語(yǔ)法規(guī)范的錯(cuò)誤稱(chēng)為語(yǔ)法錯(cuò),這類(lèi)錯(cuò)誤通常在編譯時(shí)發(fā)現(xiàn),又稱(chēng)為編譯錯(cuò)。Java編譯器能夠發(fā)現(xiàn)所有語(yǔ)法錯(cuò),給出錯(cuò)誤的位置和性質(zhì)。程序員必須及時(shí)改正語(yǔ)法錯(cuò),再重新編譯程序。2.語(yǔ)義錯(cuò)如果程序在語(yǔ)法上正確,但在語(yǔ)義上存在錯(cuò)誤,則稱(chēng)為語(yǔ)義錯(cuò),如除數(shù)為0錯(cuò)、給變量賦予超出其范圍的值、待打開(kāi)的文件不存在等。語(yǔ)義錯(cuò)不能被編譯系統(tǒng)發(fā)現(xiàn),只能到程序運(yùn)行時(shí)才能被系統(tǒng)發(fā)現(xiàn),因而又稱(chēng)為運(yùn)行錯(cuò)。在運(yùn)行時(shí),一旦發(fā)現(xiàn)了語(yǔ)義錯(cuò),Java將停止程序運(yùn)行,并給出錯(cuò)誤的位置和性質(zhì)。有些語(yǔ)義能夠被程序事先處理,程序中應(yīng)該設(shè)法避免產(chǎn)生這些錯(cuò)誤;還有一些語(yǔ)義錯(cuò)不能被程序事先處理,這些錯(cuò)誤的發(fā)生不由程序本身所控制,因此必須進(jìn)行異常處理。3.邏輯錯(cuò)如果程序通過(guò)編譯,可運(yùn)行,但運(yùn)行結(jié)果與期望值不符,則這類(lèi)錯(cuò)誤稱(chēng)為邏輯錯(cuò)。由于系統(tǒng)無(wú)法找到邏輯錯(cuò),所以邏輯錯(cuò)最難確定和排除。此時(shí),程序員必須憑借自身的程序設(shè)計(jì)經(jīng)驗(yàn),找到錯(cuò)誤原因及出錯(cuò)位置,從而改正錯(cuò)誤。6.1.2面向過(guò)程語(yǔ)言與面向?qū)ο笳Z(yǔ)言的錯(cuò)誤處理方式比較

面向過(guò)程語(yǔ)言——程序運(yùn)行效率更重要語(yǔ)言本身防范錯(cuò)誤的責(zé)任推給了程序員,使程序質(zhì)量完全依賴(lài)于程序員。程序員必須考慮并防范所有錯(cuò)誤,為每一個(gè)應(yīng)用程序設(shè)置語(yǔ)言一級(jí)的錯(cuò)誤處理機(jī)制,這對(duì)程序員的要求太高。再者,含有錯(cuò)誤處理的程序代碼臃腫,邏輯復(fù)雜,可讀性差,軟件無(wú)法維護(hù)和升級(jí)。在程序開(kāi)發(fā)過(guò)程中,程序員能夠發(fā)現(xiàn)并改正語(yǔ)法錯(cuò)和邏輯錯(cuò),但無(wú)法防范所有運(yùn)行時(shí)錯(cuò)誤,這些錯(cuò)誤的出現(xiàn)不是由程序控制的,面向過(guò)程語(yǔ)言沒(méi)有提供對(duì)這些錯(cuò)誤的防范和處理機(jī)制,只能任憑錯(cuò)誤的產(chǎn)生而導(dǎo)致程序運(yùn)行中斷。

6.1.2面向過(guò)程語(yǔ)言與面向?qū)ο笳Z(yǔ)言的錯(cuò)誤處理方式比較面向?qū)ο笳Z(yǔ)言——程序的正確性、可靠性和穩(wěn)定性更重要提供語(yǔ)言級(jí)的錯(cuò)誤防范和處理機(jī)制,即異常處理機(jī)制。異常處理是捕獲和處理運(yùn)行時(shí)錯(cuò)誤的一種機(jī)制。異常處理機(jī)制使程序具有處理錯(cuò)誤的能力,即使發(fā)生了運(yùn)行時(shí)錯(cuò)誤,應(yīng)用程序能夠捕獲異常并及時(shí)處理異常,使程序從運(yùn)行時(shí)錯(cuò)誤中很好地恢復(fù)并繼續(xù)運(yùn)行,而不會(huì)導(dǎo)致程序運(yùn)行非正常終止。異常處理是一種對(duì)異常進(jìn)行事后處理的機(jī)制。異常處理機(jī)制將運(yùn)行時(shí)錯(cuò)誤封裝成若干錯(cuò)誤類(lèi)和異常類(lèi),并提供異常處理語(yǔ)句用于在程序中實(shí)現(xiàn)對(duì)運(yùn)行時(shí)錯(cuò)誤的發(fā)現(xiàn)和及時(shí)處理。6.1.3Java的錯(cuò)誤和異常一、錯(cuò)誤與異常根據(jù)錯(cuò)誤的性質(zhì),Java將運(yùn)行時(shí)錯(cuò)誤分為兩類(lèi):錯(cuò)誤和異常。(1)錯(cuò)誤(error)錯(cuò)誤指程序運(yùn)行時(shí)遇到的硬件或操作系統(tǒng)的錯(cuò)誤,如內(nèi)存溢出、虛擬機(jī)錯(cuò)誤等。錯(cuò)誤對(duì)于程序而言是致命的,錯(cuò)誤將導(dǎo)致程序無(wú)法運(yùn)行,而且程序本身不能處理錯(cuò)誤,只能依靠外界干預(yù),否則會(huì)一直處于非正常狀態(tài)。(2)異常(exception)異常指在硬件和操作系統(tǒng)正常時(shí),程序遇到的運(yùn)行錯(cuò),如操作數(shù)超出數(shù)據(jù)范圍,文件不存在等。異常對(duì)于程序而言是非致命性的,雖然異常會(huì)導(dǎo)致程序非正常終止,但Java的異常處理機(jī)制使程序自身能夠捕獲和處理異常,由異常代碼調(diào)整程序運(yùn)行方向,但程序仍可繼續(xù)運(yùn)行。圖6.1Java程序發(fā)現(xiàn)錯(cuò)誤和異常二、錯(cuò)誤類(lèi)和異常類(lèi)Java中的所有的錯(cuò)誤類(lèi)和異常類(lèi)都是從Throwable類(lèi)派生出來(lái)的。Throwable是異常類(lèi)的根節(jié)點(diǎn),定義在java.lang包,它的子類(lèi)也定義在該包中。Throwable類(lèi)有兩個(gè)直接子類(lèi):java.lang.Error和java.lang.Exception。Error代表系統(tǒng)錯(cuò)誤類(lèi),由系統(tǒng)直接處理;Exception類(lèi)及其子類(lèi)是在程序中可捕捉到的異常。圖6.2錯(cuò)誤類(lèi)和異常類(lèi)的層次結(jié)構(gòu)(1)Error類(lèi)Error類(lèi)是錯(cuò)誤類(lèi),Error類(lèi)對(duì)象由Java虛擬機(jī)生成并拋出給系統(tǒng),有內(nèi)存溢出錯(cuò)誤、棧溢出錯(cuò)誤、動(dòng)態(tài)鏈接錯(cuò)誤等。例如,當(dāng)運(yùn)行沒(méi)有main()方法的類(lèi)時(shí),則產(chǎn)生類(lèi)定義未找到錯(cuò)誤(NoClassDefFoundError)。(2)Exception類(lèi)Exception類(lèi)是異常類(lèi),Exception類(lèi)對(duì)象是Java程序捕獲和處理的對(duì)象。每一種異常對(duì)應(yīng)Exception類(lèi)的一個(gè)子類(lèi),異常對(duì)象中包含錯(cuò)誤的位置和特征信息。每個(gè)異常類(lèi)反映一類(lèi)運(yùn)行時(shí)錯(cuò)誤,類(lèi)定義包含了該類(lèi)異常的信息和對(duì)異常進(jìn)行處理的方法。Java預(yù)定了多種通用的異常類(lèi),如除數(shù)為0的算術(shù)異常、數(shù)組下標(biāo)越界異常、空指針異常等,程序中也可以自定義異常類(lèi)。每當(dāng)程序運(yùn)行過(guò)程中發(fā)生了某個(gè)異?,F(xiàn)象,系統(tǒng)將產(chǎn)生一個(gè)相應(yīng)的異常類(lèi)對(duì)象,并交由系統(tǒng)中的相應(yīng)機(jī)制進(jìn)行處理,以避免死機(jī)、死循環(huán)或其他對(duì)系統(tǒng)不利的結(jié)果發(fā)生,保證了程序運(yùn)行的安全性。三、Error錯(cuò)誤類(lèi)的子類(lèi)

Error類(lèi)及其子類(lèi)主要用來(lái)描述一些Java運(yùn)行時(shí)的系統(tǒng)內(nèi)部錯(cuò)誤或資源枯竭導(dǎo)致的錯(cuò)誤。普通的程序不能從這類(lèi)錯(cuò)誤中恢復(fù),也無(wú)法拋出這種類(lèi)型的錯(cuò)誤,這類(lèi)錯(cuò)誤出現(xiàn)的幾率是很小的。

(1)VirtualMachineError虛擬機(jī)錯(cuò)誤OutOfMemoryError內(nèi)存溢出錯(cuò)誤StackOverflowError棧溢出錯(cuò)誤(2)LinkageError鏈接錯(cuò)誤(3)java.awt.AWTError圖形界面錯(cuò)誤

Throwable類(lèi)的一個(gè)異常類(lèi)分支是Exception類(lèi)和它的子類(lèi)。在編程中,對(duì)異常的處理主要是對(duì)這類(lèi)異常的處理。類(lèi)Exception是普通程序可以從中恢復(fù)的所有標(biāo)準(zhǔn)異常的超類(lèi)。

Exception類(lèi)又有兩個(gè)分支:從RuntimeException中派生出來(lái)的類(lèi)和從Non-RuntimeException類(lèi)中派生的類(lèi),這樣分類(lèi)的根據(jù)是錯(cuò)誤發(fā)生的原因。

四、Exception異常類(lèi)的子類(lèi)(1)RuntimeException運(yùn)行時(shí)異常類(lèi),是程序員編寫(xiě)程序不正確所導(dǎo)致的異常,理論上,程序員經(jīng)過(guò)檢查和測(cè)試可以查出這類(lèi)錯(cuò)誤。該異常可能出現(xiàn)在程序的任何地方,而且出現(xiàn)的可能性非常大,如果由程序本身去檢測(cè)運(yùn)行異常出現(xiàn)與否,將會(huì)使程序的負(fù)荷過(guò)大,因而編譯器并不要求程序去說(shuō)明或捕獲運(yùn)行時(shí)異常。(2)Non-RuntimeException非運(yùn)行時(shí)異常類(lèi),是由于一些異常的情況造成的,不是程序本身的錯(cuò)誤,可以由編譯器在編譯時(shí)檢測(cè)到的、可能會(huì)發(fā)生在方法執(zhí)行過(guò)程中的異常。比如:輸入/輸出錯(cuò)誤(IOException)、試圖為一個(gè)不存在的類(lèi)找到一個(gè)代表它的class類(lèi)的對(duì)象(ClassNotFoundException)等。這不是程序本身的錯(cuò)誤,如果這些異常情況沒(méi)有發(fā)生,程序本身仍然是完好的。如果程序沒(méi)有適當(dāng)?shù)靥幚砜赡軙?huì)引發(fā)運(yùn)行異常的語(yǔ)句,則程序?qū)⒉荒芡ㄟ^(guò)編譯器的編譯。(一)RuntimeException類(lèi)主要包括以下異常子類(lèi):·ArithmeticException算術(shù)異常類(lèi):表示遇到了異常的算術(shù)問(wèn)題,例如被0整除。·ArrayStoreException數(shù)組內(nèi)容異常類(lèi):試圖把與數(shù)組類(lèi)型不相符的值存入數(shù)組。·ClassCastException類(lèi)型強(qiáng)制轉(zhuǎn)換異常類(lèi):試圖把一個(gè)對(duì)象的引用強(qiáng)制轉(zhuǎn)換為不合適的類(lèi)型?!ndexOutOfBoundsException下標(biāo)越界異常類(lèi):下標(biāo)越界?!ullPointerException空指針異常類(lèi):試圖使用一個(gè)空的對(duì)象引用?!ecurityException違背安全原則異常類(lèi):檢測(cè)到了違反安全的行為。

1.java.lang.ArithmeticException0作除數(shù)(包括模),將產(chǎn)生這類(lèi)異常。例如:intx=0,y;y=100/x;

2.java.lang.ArrayIndexOutOfBoundsException

例如:inta[]=newint[10];a[10]=0;

產(chǎn)生運(yùn)行時(shí)異常類(lèi)對(duì)象舉例

3.

java.lang.ArrayStoreException例如:inta[]=newint[10];

booleanb[]=newboolean[10]; System.arraycopy(a,0,b,3,6);//有異常

4.java.lang.ClassCastException

例如:Objectobj=newObject();

inta[]=(int[])(obj);5.java.lang.NumerFormatException

例如:intj=Integer.parseInt(“abc”);

6.

java.lang.IndexOutOfBoundsException

例如:charch="ABC".charAt(99);

注意:2是6的子類(lèi)。

7.java.lang.NegativeArraySizeException

例如:inta[]=newint[-10];

8.

java.lang.NullPointerException

例如:inta[]=null; System.out.print(a.length);

再如:inta[]=null;a[0]=1;1.IOException異常類(lèi)IOException輸入輸出異常類(lèi),指示出現(xiàn)了某種I/O錯(cuò)誤。這個(gè)類(lèi)是由失敗的或中斷的I/O操作所產(chǎn)生的異常的總體類(lèi)。IOException:申請(qǐng)I/O操作沒(méi)有正常完成。EOFException:在輸入操作正常結(jié)束前遇到了文件結(jié)束符。FileNotFoundException:在文件系統(tǒng)中,沒(méi)有找到由文件名字符串指定的文件。(二)Non-RuntimeException類(lèi)主要包括以下異常子類(lèi):2.EmptyStackException:試圖訪問(wèn)一個(gè)空堆棧中的元素。3.NoSuchFieldException:試圖訪問(wèn)一個(gè)不存在的域。4.NoSuchMethodException:試圖訪問(wèn)不存在的方法。5.ClassNotFoundException:具有指定名字的類(lèi)或接口沒(méi)有被發(fā)現(xiàn)。6.CloneNotSupportedException:克隆一個(gè)沒(méi)有實(shí)現(xiàn)Cloneable接口的類(lèi)。7.IllegalAccessException:試圖用給出了完整的路徑信息的字符串加載一個(gè)類(lèi)。8.InstantiationException:試圖使用Class的newInstance方法創(chuàng)建一個(gè)對(duì)象實(shí)例。9.InterruptedException:當(dāng)前的線程正在等待,而另一個(gè)線程使用了Thread的interrupt方法中斷了當(dāng)前線程。(二)Non-RuntimeException類(lèi)主要包括以下異常子類(lèi):五、程序?qū)﹀e(cuò)誤與異常的三種處理方式(1)程序不能處理錯(cuò)誤(2)運(yùn)行時(shí)異?!绦驊?yīng)避免而不捕獲異常(3)非運(yùn)行時(shí)異常——必須捕獲異常對(duì)于程序無(wú)法預(yù)見(jiàn)的、由特殊環(huán)境錯(cuò)誤造成的異常,如文件沒(méi)找到、網(wǎng)絡(luò)通信失敗等,必須進(jìn)行捕獲和處理,從而保證程序正常運(yùn)行,保證程序的可靠性和安全性。6.2Java的異常處理6.2.1異常處理機(jī)制的優(yōu)點(diǎn)例6.1異常處理方法演示。publicclassExceptionDemo{ staticint[]IntArrayAdd(int[]a,int[]b) {

int[]c=newint[a.length];

for(inti=0;i<c.length;i++) c[i]=a[i]+b[i]; returnc;}

publicstaticvoidmain(String[]args) {

int[]a=newint[20];

int[]b=newint[10];

for(inti=0;i<20;i++) a[i]=i;

for(inti=0;i<10;i++) b[i]=i;

try{

int[]c=IntArrayAdd(a,b);

for(inti=0;i<c.length;i++) System.out.print(""+c[i]); }catch(Exceptione){

System.out.println("Thereisanerror!"); } }}程序運(yùn)行結(jié)果為:

Thereisanerror!

從第2章有關(guān)數(shù)組的知識(shí)可以知道,程序6.1的main方法在調(diào)用方法IntArrayAdd對(duì)數(shù)組b訪問(wèn)時(shí)下標(biāo)超界,產(chǎn)生一個(gè)異常。由于程序6.1采用了Java語(yǔ)言中的異常處理方法,程序執(zhí)行流程發(fā)生變化,轉(zhuǎn)到語(yǔ)句System.out.println(“Thereisanerror!”)執(zhí)行。觀察一下程序6.1可以發(fā)現(xiàn),程序中的錯(cuò)誤在IntArrayAdd方法中發(fā)生,但是該方法中并沒(méi)有錯(cuò)誤處理語(yǔ)句,既沒(méi)有用返回值標(biāo)志錯(cuò)誤發(fā)生,也沒(méi)有設(shè)置一個(gè)main方法和IntArrayAdd方法可以共同訪問(wèn)的變量用于傳遞錯(cuò)誤信息。那么,錯(cuò)誤信息是怎樣從IntArrayAdd方法傳遞到main方法的呢?實(shí)際上IntArrayAdd方法在超界訪問(wèn)數(shù)組元素時(shí)拋擲了一個(gè)異常,創(chuàng)建了一個(gè)異常對(duì)象用于存儲(chǔ)錯(cuò)誤信息,由于IntArrayAdd方法沒(méi)有處理該異常,Java虛擬機(jī)終止IntArrayAdd方法的執(zhí)行,然后自動(dòng)返回到main方法,將流程轉(zhuǎn)入異常處理部分。Java語(yǔ)言的異常處理機(jī)制的優(yōu)點(diǎn)(1)從語(yǔ)法上看,異常處理語(yǔ)句將程序正常代碼與錯(cuò)誤代碼分開(kāi),使程序的結(jié)構(gòu)清晰,算法重點(diǎn)突出,可讀性強(qiáng)。例如程序6.1的main方法中先調(diào)用IntArrayAdd方法然后輸出結(jié)果,中間并沒(méi)有插入錯(cuò)誤處理的代碼,而按照傳統(tǒng)的方法,程序的結(jié)構(gòu)應(yīng)該是這樣的:調(diào)用IntArrayAdd方法:

if(發(fā)生錯(cuò)誤)

輸出錯(cuò)誤信息

else

輸出結(jié)果當(dāng)錯(cuò)誤類(lèi)型較多,需要分別處理時(shí),采用這種方法很顯然會(huì)使程序流程變得十分復(fù)雜。Java語(yǔ)言的異常處理機(jī)制的優(yōu)點(diǎn)(2)異常處理機(jī)制帶來(lái)的另一個(gè)好處是錯(cuò)誤的傳播。

Java異常會(huì)自動(dòng)在方法調(diào)用堆棧中傳播,例如程序6.1異常從IntArrayAdd方法自動(dòng)傳遞到main方法。(3)Java異常處理機(jī)制克服了傳統(tǒng)方法的錯(cuò)誤信息有限的問(wèn)題,可以針對(duì)不同的錯(cuò)誤類(lèi)型定義不同的異常類(lèi)。

異常處理機(jī)制會(huì)根據(jù)異常對(duì)象的類(lèi)型尋找匹配的錯(cuò)誤處理代碼。(4)從運(yùn)行效果看,異常處理語(yǔ)句使程序具有處理錯(cuò)誤的能力。即使發(fā)生了運(yùn)行錯(cuò),應(yīng)用程序能夠捕獲異常并及時(shí)處理異常,使程序從運(yùn)行錯(cuò)誤中很好地恢復(fù)并繼續(xù)運(yùn)行,而不會(huì)導(dǎo)致程序運(yùn)行非正常終止。而且,如果當(dāng)前方法沒(méi)有能力處理異常,還可以將異常轉(zhuǎn)交給調(diào)用者處理。6.2.2異常處理機(jī)制

Java提供了異常處理機(jī)制來(lái)處理異常。分為三個(gè)步驟:

1.拋出異常

Java是這樣規(guī)定的:當(dāng)語(yǔ)義限制被違反時(shí),將會(huì)拋出(throw)異常,即產(chǎn)生一個(gè)異常事件,生成一個(gè)異常對(duì)象,并把它提交給運(yùn)行系統(tǒng),再由運(yùn)行系統(tǒng)尋找相應(yīng)的代碼來(lái)處理異常。一個(gè)異常對(duì)象可以由Java虛擬機(jī)來(lái)產(chǎn)生,也可以由運(yùn)行的方法生成。異常對(duì)象中包含了異常事件類(lèi)型、程序運(yùn)行狀態(tài)等必要信息。

2.捕獲異常異常拋出后,運(yùn)行時(shí)系統(tǒng)從生成異常對(duì)象的代碼開(kāi)始,沿方法的調(diào)用棧進(jìn)行查找,直到找到包含相應(yīng)處理的方法代碼,并把異常對(duì)象交給該方法為止,這個(gè)過(guò)程稱(chēng)為捕獲(catch)異常。

3.處理異常對(duì)異常對(duì)象執(zhí)行相應(yīng)操作,異常對(duì)象由捕獲它的語(yǔ)句進(jìn)行處理。

6.2.3異常的捕獲除了繼承自Error或RuntimeException的異常不需要處理之外,其他的異常都要進(jìn)行處理,如例6.2。在程序中經(jīng)常要做的一件事就是捕獲、處理異常。異常處理代碼塊(catch{})中可以寫(xiě)上任何代碼,事實(shí)上只要對(duì)該捕獲的異常進(jìn)行“catch”就可以,不作任何實(shí)質(zhì)處理也可以通過(guò)編譯。例6.2缺省的異常處理的情況。

publicclassDefaultException{publicstaticvoidmain(Stringargs[]){

inta,b=0;

a=2/b;//此處有異常

System.out.println(“a=”+a);//不運(yùn)行此行

}}異常處理的格式:try{//接受監(jiān)視的程序塊,在此區(qū)域內(nèi)發(fā)生的異常,由catch中指定的程序處理}//trycatch(異常類(lèi)名1異常對(duì)象名1){//處理異常;}//catchcatch(異常類(lèi)名2異常對(duì)象名2){//處理異常;}//catch……finally{//不論發(fā)生什么異常(或者不發(fā)生任何異常),都要執(zhí)行的部分}//finally圖6.3異常處理語(yǔ)句的執(zhí)行流程將可能發(fā)生異常的程序代碼放置在try程序塊中。程序運(yùn)行過(guò)程中,如果該塊內(nèi)的代碼沒(méi)有出現(xiàn)任何異常,則正常執(zhí)行,后面的各catch塊不起任何作用。但如果該塊內(nèi)的代碼出現(xiàn)了異常,系統(tǒng)將終止try塊的執(zhí)行,自動(dòng)跳轉(zhuǎn)到所發(fā)生的異常類(lèi)對(duì)應(yīng)的catch塊,執(zhí)行該塊中的代碼。無(wú)論有沒(méi)有異常,finally語(yǔ)句都會(huì)被執(zhí)行。如例6.3。catch子句捕獲異常的匹配規(guī)則如下:拋出異常對(duì)象與catch子句參數(shù)類(lèi)型相同拋出異常對(duì)象為catch子句參數(shù)類(lèi)的子類(lèi)按照先后順序捕獲拋出異常對(duì)象,只捕獲一次若找不到相匹配的catch語(yǔ)句,將執(zhí)行缺省的異常處理,如例6.4。因此,通常最后一個(gè)catch子句的異常類(lèi)參數(shù)聲明為Exception,這樣能夠保證捕獲和處理所有異常對(duì)象。異常處理的格式說(shuō)明:例6.3如果try塊內(nèi)的代碼出現(xiàn)了異常,系統(tǒng)將終止try塊的執(zhí)行,自動(dòng)跳轉(zhuǎn)到所發(fā)生的異常類(lèi)對(duì)應(yīng)的catch塊。publicclassTryCatchTest{publicstaticvoidmain(Stringargs[]){

inta=99,b=0,c;

try{

System.out.println("產(chǎn)生異常之前"); c=a/b;//該行有異常

System.out.println("產(chǎn)生異常之后"); }catch(ArrayIndexOutOfBoundsExceptione){

System.out.println("處理下標(biāo)越界異常"); }catch(ArithmeticExceptione){

System.out.println("處理算術(shù)異常"); }

System.out.println("異常處理結(jié)束");}}程序運(yùn)行的結(jié)果:產(chǎn)生異常之前處理算術(shù)異常異常處理結(jié)束例6.4用catch語(yǔ)句捕捉異常時(shí),若找不到相匹配的catch語(yǔ)句,將執(zhí)行缺省的異常處理。publicclassTC2{publicstaticvoidmain(String[]args){

System.out.println(“這是一個(gè)異常處理的例子\n”);try{

inti=10;i/=0;}catch(IndexOutOfBoundsExceptione){

System.out.println("異常是:"+e.getMessage());}finally{

System.out.println("finally

語(yǔ)句被執(zhí)行");}}}程序運(yùn)行的結(jié)果:這是一個(gè)異常處理的例子對(duì)于一個(gè)try塊,可以對(duì)應(yīng)多個(gè)catch塊,用于對(duì)多個(gè)異常類(lèi)進(jìn)行捕獲。每個(gè)catch后的異常類(lèi)名應(yīng)不同,Java語(yǔ)言根據(jù)異常對(duì)象的類(lèi)型從上向下匹配,執(zhí)行第一個(gè)與之匹配的catch塊。如果要捕獲的諸類(lèi)之間沒(méi)有繼承關(guān)系,各類(lèi)的catch塊的順序就無(wú)關(guān)緊要,但如果它們之間有繼承關(guān)系,那么應(yīng)該將子類(lèi)的catch塊放置在父類(lèi)的catch塊之前。例如,當(dāng)程序中數(shù)組下標(biāo)超界時(shí),Java拋擲出ArrayIndexOutOfBoundsExeption類(lèi)的異常對(duì)象,該異常類(lèi)是Exception的派生類(lèi),因此應(yīng)將ArrayIndexOutOfBoundsExeption異常類(lèi)的catch塊放在Exception的前面。異常處理的格式說(shuō)明:inta[]=newint[10];try{

for(inti=0;i<=10;i++) a[i]=i;}catch(ArrayIndexOutOfBoundsExeptione){

System.out.println("ArrayIndexoutofBounds");}catch(Exceptione){

System.out.println("Thereisanexception");}該程序段將輸出:ArrayIndexoutofBounds而如果將兩個(gè)catch塊的順序?qū)φ{(diào),則變成下面的形式:inta[]=newint[10];try{for(inti=0;i<=10;i++) a[i]=i;}catch(Exceptione){

System.out.println("Thereisanexception");}

catch(ArrayIndexOutOfBoundsExeptione){

System.out.println("ArrayIndexoutofBounds");}將執(zhí)行第一個(gè)catch塊,輸出:

Thereisanexception其中finally塊是個(gè)可選項(xiàng),finally是異常處理的統(tǒng)一出口,如果有finally代碼塊,則不論怎樣都會(huì)執(zhí)行finally代碼塊中的內(nèi)容。因此,finally代碼塊中常常放一些清理現(xiàn)場(chǎng)的代碼,它可以保證不論出現(xiàn)什么異常都不致于造成嚴(yán)重后果。不過(guò),finally代碼塊不是必須的,有些情況下并不必寫(xiě)finally代碼塊。finally語(yǔ)句不被執(zhí)行的唯一情況是在try塊內(nèi)執(zhí)行終止程序的System.exit()方法。注意:如果在調(diào)用能夠產(chǎn)生異常的方法時(shí)沒(méi)有進(jìn)行捕獲和處理,將不能通過(guò)編譯。異常處理的格式說(shuō)明:例6.5異常處理的執(zhí)行順序。publicclassFinallyBlock{ publicstaticvoidmain(String[]args) {

inti=0; Stringgreetings[]={ "Helloworld!", "No,Imeanit!", "HELLOWORLD!!“};

while(i<4){ try{System.out.println(greetings[i]); }catch(ArrayIndexOutOfBoundsExceptione){

System.out.println("Re-settingIndexValue"); i=-1; }finally{

System.out.println("Thisisalwaysprinted"); } i++; } }}程序運(yùn)行時(shí)重復(fù)輸出下面的內(nèi)容,可按Ctrl+C終止:Helloworld!ThisisalwaysprintedNo,Imeanit!ThisisalwaysprintedHELLOWORLD!!ThisisalwaysprintedRe-settingIndexValueThisisalwaysprinted練習(xí)1:編寫(xiě)程序。程序運(yùn)行結(jié)果如下:捕獲算術(shù)異常!i=0a[1]/1=6i=1a[2]/2=3i=2a[3]/3=2i=3捕獲數(shù)組下標(biāo)越界異常!i=4繼續(xù)!publicclassTry2{publicstaticvoidmain(Stringargs[]){

inti=0;

inta[]={5,6,7,8};

for(i=0;i<5;i++){try{

System.out.print("a["+i+"]/"+i+"="+(a[i]/i));}

catch(ArrayIndexOutOfBoundsExceptione){

System.out.print("捕獲數(shù)組下標(biāo)越界異常!");}

catch(ArithmeticExceptione){

System.out.print("捕獲算術(shù)異常!");}

catch(Exceptione){

System.out.print("捕獲"+e.getMessage()+"異常!");//顯示異常信息}finally{

System.out.println("i="+i);}}

System.out.println("繼續(xù)!");}}TestNo:1

零作除數(shù)!在finally塊中!TestNo:2

數(shù)組下標(biāo)越界!在finally塊中!TestNo:3

下標(biāo)越界!在finally塊中!TestNo:4

在finally塊中!練習(xí)2:用for和switch編寫(xiě)程序,程序運(yùn)行結(jié)果如下:publicclasstestFinally{publicstaticvoidmain(Stringargs[]){

inta,b=0;

for(inti=0;i<=3;i++){

System.out.println("TestNo:"+(i+1));

try{ switch(i){ case0:a=3/b; break; case1:intc[]=newint[10]; c[10]=0; break; case2:charch="ABC".charAt(99); break; case3:return; } }catch(ArithmeticExceptione){

System.out.println(“零作除數(shù)!”); }catch(ArrayIndexOutOfBoundsExceptione){

System.out.println("數(shù)組下標(biāo)越界!");}catch(IndexOutOfBoundsExceptione){

System.out.println("下標(biāo)越界!");}finally{

System.out.println("在finally塊中!"); }}}}

6.2.4異常的拋擲上面講述的捕獲異常是針對(duì)程序在運(yùn)行過(guò)程中產(chǎn)生的可以預(yù)知、必須及時(shí)處理而且有明確的處理對(duì)策的異常,其結(jié)果可以給用戶(hù)提供更多的、更友好的錯(cuò)誤信息。但是有時(shí)也會(huì)碰到錯(cuò)誤形式不確定的情況,隨之而來(lái)的是不能或很難完整描述具體處理的方法。對(duì)于這種在程序中不能匹配捕獲的異常,Java是不允許置之不理的,于是可以采取向外拋出的辦法。

1.throw語(yǔ)句

throw語(yǔ)句格式:

<throw><new><異常類(lèi)名()>;

例如:

thrownewException();

該語(yǔ)句直接調(diào)用Exception類(lèi)的構(gòu)造方法創(chuàng)建一個(gè)Exception類(lèi)的對(duì)象并拋擲該對(duì)象。

Exception類(lèi)從Throwable類(lèi)派生而來(lái),含有兩個(gè)構(gòu)造方法:

●publicException();●publicException(Stringmsg)。

根據(jù)錯(cuò)誤類(lèi)型的不同,創(chuàng)建的異常對(duì)象的類(lèi)型也不相同。

throw語(yǔ)句的說(shuō)明:

Throw語(yǔ)句是主動(dòng)產(chǎn)生一個(gè)異常而非動(dòng)態(tài)拋出。當(dāng)程序執(zhí)行到throw語(yǔ)句處,就立即人為地拋出一個(gè)異常,然后把控制轉(zhuǎn)移到一個(gè)相應(yīng)的catch塊,不再執(zhí)行throw后面的語(yǔ)句。在程序中使用throw語(yǔ)句來(lái)拋出異常,該異??梢栽谠摮绦蛑羞M(jìn)行捕獲、處理;也可以在調(diào)用它的程序中被處理。例6.6throw語(yǔ)句的使用,運(yùn)行結(jié)果如圖所示。publicclassTC5{staticvoidthrowProcess(){try{

thrownewNullPointerException("空指針異常");}

catch(NullPointerExceptione){

System.out.println("\n在throwProcess

方法中捕獲一個(gè)"+e.getMessage());

throwe;}}

publicstaticvoidmain(Stringargs[]){try{

throwProcess();}catch(NullPointerExceptione){

System.out.println("再次捕獲:"+e);}}}練習(xí)3:產(chǎn)生一個(gè)數(shù)組越界的異常,既在本方法體中處理,又通過(guò)throw語(yǔ)句將異常對(duì)象提交給調(diào)用者,以進(jìn)行再次處理。程序運(yùn)行結(jié)果如下:數(shù)組下標(biāo)越界!下標(biāo)越界!在finally塊中!

publicclassThrowException{publicstaticvoidTest(){ try{

intc[]=newint[10]; c[10]=0; }catch(ArrayIndexOutOfBoundsExceptione){

System.out.println("\t

數(shù)組下標(biāo)越界!"); throwe;//拋出點(diǎn)

//System.out.println("\t產(chǎn)生異常后!"); } }publicstaticvoidmain(Stringargs[]){ try{

Test(); }catch(IndexOutOfBoundsExceptione){

System.out.println("\t

下標(biāo)越界!"); }finally{

System.out.println("\t

在finally塊中!"); }}}

2.throws子句

Throws子句總是和方法說(shuō)明出現(xiàn)在一起。方法說(shuō)明告訴編譯器該方法可能會(huì)產(chǎn)生哪些異常,從而要求它的調(diào)用者必須考慮處理這些異常。一個(gè)方法不處理它產(chǎn)生的異常,而是沿著調(diào)用層次向上傳播,由調(diào)用它的方法來(lái)處理這些異常。建議:在多人合作寫(xiě)程序時(shí),一個(gè)方法中產(chǎn)生的異常,最好在該方法中進(jìn)行處理,不要將異常傳播給其他人處理。圖7.2throws異常的拋出及處理方法一方法二異常調(diào)用拋出處理Throws子句格式:在方法定義的頭部加上:throws異常類(lèi)名列表

<返回值類(lèi)型><方法名><([參數(shù)])><throws><異常類(lèi)名列表>{}例如:Thread類(lèi)的方法sleep的定義為

publicstaticnativevoidsleep(longmills)throwsInterruptedException例6.7由調(diào)用者進(jìn)行throws子句中的異常處理。importjava.io.*;publicclasstestThrows{publicstaticStringreadString()throws

IOException{

int

ch; Stringr="";

booleandone=false;

while(!done){

ch=System.in.read();

if(ch<0||ch==0xd)done=true; else r=r+(char)ch; } returnr;}Enter讀入緩沖區(qū)的字節(jié)總數(shù),如果因?yàn)橐呀?jīng)到達(dá)文件末尾而沒(méi)有更多的數(shù)據(jù),則返回-1。

publicstaticvoidmain(Stringargs[]){ Stringstr; try{

str=readString(); }catch(IOExceptione){

System.out.println("產(chǎn)生了輸出/輸出異常"); return; }

System.out.println("整數(shù)是:"+Integer.parseInt(str));}}將字符串轉(zhuǎn)換成整數(shù)練習(xí)4:閱讀程序,說(shuō)明程序運(yùn)行的結(jié)果。classTC6{staticvoidmathod()throwsIllegalAccessException{

System.out.println("\n在mathod

中拋出一個(gè)異常");thrownewIllegalAccessException();}publicstaticvoidmain(Stringargs[]){try{

mathod();}catch(IllegalAccessExceptione){

System.out.println("在main中捕獲異常:"+e);}}}沒(méi)有訪問(wèn)權(quán)限程序的運(yùn)行結(jié)果如圖所示:練習(xí)5:編寫(xiě)程序,在test()方法中使用5/0初始化intTemp,將觸發(fā)ArithmaticException異常,但test方法不對(duì)該異常捕獲和處理,而希望調(diào)用它的方法對(duì)該異常進(jìn)行捕獲和處理。

3.拋出異常的綜合實(shí)例程序6.11演示了try-catch和throw語(yǔ)句的使用,該程序在KeyboardInput類(lèi)中定義了兩個(gè)靜態(tài)方法ReadInt和ReadDouble,從標(biāo)準(zhǔn)輸入設(shè)備讀取int、double類(lèi)型數(shù)據(jù)。首先調(diào)用ReadLine方法讀取一行字符串,然后將該字符串轉(zhuǎn)換為int、double類(lèi)型數(shù)據(jù)。如果在轉(zhuǎn)換的過(guò)程中發(fā)生錯(cuò)誤,輸入了錯(cuò)誤的數(shù)據(jù),則拋擲NumberFormatException類(lèi)的異常,ReadInt和ReadDouble方法捕捉該異常,然后拋擲Exception異常。ExceptionDemo類(lèi)在main方法中捕捉異常,調(diào)用Exception類(lèi)的方法getMessage獲取錯(cuò)誤信息。

例6.8異常處理實(shí)例。importjava.io.IOException;classKeyboardInput{ staticint

ReadInt()throwsException { Stringstr=ReadLine(); try{ returnnewInteger(str).intValue(); //將讀入的字符串轉(zhuǎn)換為int}catch(NumberFormatExceptione){ thrownewException("輸入數(shù)據(jù)錯(cuò)誤"); } }

staticdoubleReadDouble()throwsException{ Stringstr=ReadLine(); try{ returnnewDouble(str).doubleValue();//將讀入的字符串轉(zhuǎn)換為double}catch(NumberFormatExceptione){ thrownewException("輸入數(shù)據(jù)錯(cuò)誤"); } }

staticStringReadLine() { charin; Stringinputstr=""; try{in=(char)System.in.read(); while(in!='\n'){ if(in!='\r')

inputstr=inputstr+in; in=(char)System.in.read(); } }catch(IOExceptione){

inputstr=""; }returninputstr; }}\n表示回車(chē)\r表示換行publicclassExceptionDemo{ publicstaticvoidmain(String[]args) { try{

System.out.println("Theinputdoubleis"+KeyboardInput.ReadDouble());

System.out.println("Theinputintegeris"+KeyboardInput.ReadInt()); }catch(Exceptione){

System.out.println(e.getMessage()); } }}classTC7{staticvoidmathodA(){try{

System.out.println("\nmathodA

拋出一個(gè)異常");thrownewRuntimeException();}finally{

System.out.println("執(zhí)行mathodA

的finally");}}練習(xí)6:閱讀程序,說(shuō)明程序運(yùn)行的結(jié)果。staticvoidmathodB(){try{

System.out.println("mathodB

正常返回");return;}finally{

System.out.println("執(zhí)行mathodB

的finally");}}publicstaticvoidmain(Stringargs[]){try{

mathodA();}catch(Exceptione){mathodB();}}}程序的運(yùn)行結(jié)果如圖所示:上例中finally子句的執(zhí)行順序說(shuō)明:當(dāng)一個(gè)異常被拋出時(shí),程序的執(zhí)行就不再是連續(xù)的了,會(huì)跳過(guò)某些語(yǔ)句,甚至?xí)捎跊](méi)有與之匹配的catch子句而過(guò)早地返回。有時(shí)要確保一段代碼不管發(fā)生什么異常都能被執(zhí)行是必要的,finally子句就是用來(lái)標(biāo)識(shí)這樣一段代碼的。即使沒(méi)有catch子句,finally語(yǔ)句塊也會(huì)在執(zhí)行了try語(yǔ)句塊后立即被執(zhí)行。每個(gè)try語(yǔ)句至少都要有一個(gè)與之相配的catch或finally子句。從一個(gè)方法返回到調(diào)用它的另外一個(gè)方法,或者是通過(guò)return語(yǔ)句,或者是通過(guò)一個(gè)沒(méi)有被捕獲的異常,但finally子句總是在返回前執(zhí)行。練習(xí)7:編寫(xiě)程序,編譯時(shí)對(duì)異常情況的檢查不是方法中產(chǎn)生的所有異常錯(cuò)誤都必須被捕獲或聲明,Error和RuntimeException錯(cuò)誤就不要求處理。Error屬于嚴(yán)重的系統(tǒng)錯(cuò)誤,沒(méi)有辦法在程序中處理。而RuntimeException在運(yùn)行時(shí)應(yīng)該在編寫(xiě)程序中避免發(fā)生錯(cuò)誤。對(duì)于非運(yùn)行時(shí)異常,則要求必須捕獲或聲明。也就是說(shuō),要么通過(guò)try-catch語(yǔ)句捕獲,要么將這些異常放在方法的throws語(yǔ)句中聲明,否則無(wú)法通過(guò)編譯。子類(lèi)方法拋出的異常只能是父類(lèi)方法拋出異常的同類(lèi)或子類(lèi)。也就是說(shuō),子類(lèi)不能拋出比父類(lèi)更多的異常。

6.3自定義異常類(lèi)在選擇要拋出異常類(lèi)型時(shí),不一定非要使用Java平臺(tái)提供的異常類(lèi),更多的情況下是拋出程序員自己創(chuàng)建的異常,以滿足對(duì)某些特定應(yīng)用環(huán)境下的異常處理需要。這就涉及異常的創(chuàng)建問(wèn)題,即創(chuàng)建自己的異常。自定義異常類(lèi)的格式:自定義異常類(lèi)型是從Exception類(lèi)中派生的,所以要使用下面的聲明語(yǔ)句來(lái)創(chuàng)建:

<class><自定義異常名><extends><Exception>{…}用戶(hù)定義異常類(lèi)是通過(guò)派生Exception類(lèi)來(lái)創(chuàng)建的,這種異常類(lèi)可以包含一個(gè)“普通”類(lèi)所包含的任何東西。下面就是一個(gè)用戶(hù)定義異常類(lèi)的例子,它包含一個(gè)構(gòu)造函數(shù)、幾個(gè)變量以及方法。例如:

classMyExceptionextendsException{privateint

ErrorCode;

MyException(int

ecode){super("自定義的異常類(lèi)型");

ErrorCode=ecode;}publicint

getErrorCode(){ returnErrorCode;}}

定義上面的異常類(lèi)后可以通過(guò)下面的語(yǔ)句拋擲MyException類(lèi)的異常:thrownewMyException(1);通過(guò)繼承Exception類(lèi)或它的子類(lèi),實(shí)現(xiàn)自定義異常類(lèi);對(duì)于自定義異常,必須采用throw語(yǔ)句拋出異常,這種類(lèi)型的異常不會(huì)自行產(chǎn)生??傮w上分為兩步:第1步:定義異常類(lèi)。第2步:定義異常對(duì)象,并拋出該對(duì)象。第1步:定義異常類(lèi)。例如:classuserExceptionextendsException{

intn=0;//計(jì)數(shù)器

userException(){n++; }

userException(Strings){ super(s); n++; }

Stringshow(){return"自定義異常對(duì)象:"+n; }}第2步:定義異常對(duì)象,并拋出該對(duì)象。例如:publicclasstestException{ staticvoidTest()throwsuserException{

userExceptione; e=newuserException("自定義異常"); throwe;

//=thrownewuserException("自定義異常"); } publicstaticvoidmain(Stringargs[]){ try{ Test(); }catch(userExceptione){

System.out.println(e.show()); } }}練習(xí)7:閱讀程序,說(shuō)明程序運(yùn)行的結(jié)果。<=0)}}例6.12異常類(lèi)的定義、異常拋鄭和捕捉。程序運(yùn)行后從鍵盤(pán)輸入10個(gè)英文字母,如果輸入非英文字母的字符,則拋擲自定義的notLetterException類(lèi)型的異常。

importjava.io.IOException;

classnotLetterExceptionextendsException{ //異常類(lèi)定義

publicnotLetterException(){ super("NotanEnglishletter"); }}publicclassgetLetter{ voidReadLetter(char[]s)throwsnotLetterException,IOException{ charc;

for(inti=0;i<s.length;i++){ c=(char)System.in.read(); if((c>='A'&&c<='Z')||(c>='a'&&c<='z')) s[i]=c; elsethrownewnotLetterException();//異常的拋擲

} }

publicstaticvoidmain(String[]args) { char[]s=newchar[10];

getLetterg=newgetLetter(); try{

g.ReadLetter(s); }catch(notLetterExceptione){//捕捉自定義的異常

System.out.println(e.getMessage()); }catch(IOExceptione){

System.out.println("I/Oerror"); } }}練習(xí)8:編寫(xiě)程序,程序的運(yùn)行結(jié)果如下圖。classMyExceptionextendsException{privateintx;

MyException(inta){x=a;}publicStringtoString(){return"MyException";}}publicclassTC8{staticvoidmathod(inta)throwsMyException{//聲明方法會(huì)拋出MyException

System.out.println("\t此處引用mathod("+a+")");if(a>10)thrownewMyException(a);//主動(dòng)拋出

System.out.println("正常返回");}

publicstaticvoidmain(Stringargs[]){try{

System.out.println("\n進(jìn)入監(jiān)控區(qū),執(zhí)行可能發(fā)生異常的程序段");mathod(8);mathod(20);mathod(6);}catch(MyExceptione){

System.out.println("\t程序發(fā)生異常并在此處進(jìn)行處理");

System.out.println("\t發(fā)生的異常為:"+e.toString());}

System.out.println("這里可執(zhí)行其它代碼");}}

異常處理常用調(diào)試方法

在程序中增加輸出變量的信息。例如:System.out.println("x="+x);通過(guò)this輸出當(dāng)前對(duì)象的狀態(tài)。例如:System.out.println(“對(duì)象:”+this);用printstackTrace()輸出異常對(duì)象的調(diào)用棧;用getMessage()方法獲取異常信息;用getClass()和getName()獲取異常類(lèi)名。classuserExceptionextendsException{ publicuserException(){ super("自定義異常"); }}

publicclassgetMessages{ publicstaticvoidm1()throwsuserException{ m2(); } publicstaticvoidm2()throwsuserException{ thrownewuserException(); }例6.13異常處理的常用調(diào)試方法。publicstaticvoidmain(Stringargs[]){try{ m1();}catch(userExceptione){

System.out.println(e.getMessage());

e.printStackTrace();

System.out.println(“異常類(lèi)型:”+

e.getClass().getName()); } }}程序輸出結(jié)果:自定義異常userException:自定義異常

atgetMessages.m2(getMessages.java:13)atgetMessages.m1(getMessages.java:10)atgetMessages.main(getMessages.java:19)異常類(lèi)型:userException

異常處理的注意內(nèi)容

當(dāng)一個(gè)異常一直傳遞到main方法(程序調(diào)用的最高層)還沒(méi)有被捕獲,那么JVM將捕獲該異常并給出相應(yīng)的異常信息且中止引發(fā)異常之后的操作,這對(duì)于用戶(hù)來(lái)說(shuō)實(shí)際上就是程序已經(jīng)崩潰。因此自定義的異常類(lèi)名不宜放在main方法聲明時(shí)的throws列表中。Catch子句不能圖方便只寫(xiě)catch(Exceptione){}。因?yàn)樗鼘⒉东@所有的異常,實(shí)際上無(wú)法給用戶(hù)提供實(shí)質(zhì)性的異常提示信息,也不便于程序調(diào)試。編寫(xiě)程序時(shí)對(duì)異常的處理與不處理的區(qū)別在于我們是否能夠控制所有的操作。例6.14比較兩個(gè)程序的運(yùn)行結(jié)果。

publicclassA{publicstaticvoidmain(String[]args){

intb=0;b=12/0;//對(duì)異常不處理

System.out.println(“b=”+b);}}執(zhí)行結(jié)果:Exceptioninthread“main”java.lang.ArithmeticException:/byzeroatA.main<A.java:4>

publicclassA{publicstaticvoidmain(String[]args){

intb=0;try{b=12/0;//對(duì)異常進(jìn)行處理

}catch(ArithmeticExceptione){

e.printStackTrace(System.err);}

System.out.println(“b=”+b);}}執(zhí)行結(jié)果:Java.lang.ArithmeticException:/byzeroatA.main<A.java:5>b=06.4編程實(shí)例程序6.14實(shí)現(xiàn)了一個(gè)簡(jiǎn)易的計(jì)算器,該程序由兩個(gè)文件組成。文件Calculator.java中定義了一個(gè)類(lèi)Calculator,該類(lèi)用于實(shí)現(xiàn)計(jì)算器的功能,但不包括輸入輸出。文件AppCal.java中定義了類(lèi)AppCal,其中包含main方法。AppCal的run方法從鍵盤(pán)接收輸入,調(diào)用Calculator的方法進(jìn)行處理。例如,若從鍵盤(pán)輸入3+2*3,則程序按照輸入的順序計(jì)算,最后輸出結(jié)果15?!境绦?.14】簡(jiǎn)易計(jì)算器。//Calculator.javapublicclassCalculator{ privateintstatus=0;//計(jì)算器當(dāng)前狀態(tài)

//0表示將已計(jì)算結(jié)果放入操作數(shù)1,等待運(yùn)算符,或重新輸入操作數(shù)

//1表示正在輸入操作數(shù)1 //2表示已輸入運(yùn)算符,等待輸入操作數(shù)2 //3表示正在輸入操作數(shù)2

privateStringnum1="0",num2="";//存儲(chǔ)運(yùn)算數(shù)

privatecharOp;//存儲(chǔ)運(yùn)算符

publicStringDisplayStr="0";//存儲(chǔ)運(yùn)算結(jié)果

//計(jì)算器回到初始狀態(tài)

publicvoidinit() { status=0; num1="0";

DisplayStr="0"; }

//處理一個(gè)按鍵

voidKeyProcess(charkey){ switch(status){ case0:

if((key>='0'&&key<='9')||key=='.'){ status=1; num1=""+key;

DisplayStr=num1; } elseif(key=='+'||key=='-'||key=='*'||key=='/'){ Op=key; status=2;} break;

case1: if((key>='0'&&key<='9')||key=='.'){ status=1; num1=num1+key;

DisplayStr=num1; } elseif(key=='='){status=0; } elseif(key=='+'||key=='-'||key=='*'||key=='/'){ Op=key; status=2; } break;

case2: if((key>='0'&&key<='9')||key=='.'){ status=3; num2=""+key;

DisplayStr=num2; } elseif(key=='='){ status=0; } break;

case3: if((key>='0'&&key<='9')||key=='.'){ num2=num2+key;

DisplayStr=num2; } elseif(key=='='){ Cal();

DisplayStr=num1; status=0; }elseif(key=='+'||key=='-'||key=='*'||key=='/'){ Cal();

DisplayStr=num1; status=2; Op=key; } break; } }//計(jì)算結(jié)果

voidCal() { doublen1=newDouble(num1).doubleValue();//使用Double

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 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ì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

評(píng)論

0/150

提交評(píng)論