<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Decode360's Blog

    業(yè)精于勤而荒于嬉 QQ:150355677 MSN:decode360@hotmail.com

      BlogJava :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 ::  :: 管理 ::
      302 隨筆 :: 26 文章 :: 82 評(píng)論 :: 0 Trackbacks
    異常處理

    ?
    ??? 任何一個(gè)軟件或程序都可能在運(yùn)行的過(guò)程中出現(xiàn)故障,問(wèn)題的關(guān)鍵是故障出現(xiàn)以后如何處理?誰(shuí)來(lái)處理?怎樣處理?處理后系統(tǒng)能否恢復(fù)正常的運(yùn)行?本章在介紹Java處理這類(lèi)問(wèn)題基本方法的基礎(chǔ)上,討論包含異常處理的Java程序的設(shè)計(jì)方法。
    ?
    ?
    1、異常和異常處理的兩種方法
    ?
    ??? 異常是指程序在執(zhí)行過(guò)程中出現(xiàn)的意外事件。異常通常會(huì)使程序的正常流程被打斷。例如,程序在向磁盤(pán)中讀寫(xiě)文件時(shí)磁盤(pán)出現(xiàn)問(wèn)題、算術(shù)運(yùn)算中被除數(shù)為0、數(shù)組下標(biāo)越界、輸入/輸出時(shí)文件不存在、輸入數(shù)據(jù)格式不正確、程序本身錯(cuò)誤,等等。
    ??? 一般情況下,程序中需要處理異常情況,通過(guò)對(duì)異常情況的處理,可以使程序的執(zhí)行流程繼續(xù)下去,并進(jìn)行一些異常處理;否則,程序的正常執(zhí)行流程會(huì)被中斷。

    ?
    1、異常的基本類(lèi)型
    ?
    ??? 異常處理的第一步是確定異常的類(lèi)型,常見(jiàn)的異常情況一般分為以下幾類(lèi):
    ??? 用戶(hù)輸入錯(cuò)誤:指用戶(hù)鍵盤(pán)輸入錯(cuò)誤,輸入格式不對(duì)或輸入內(nèi)容不符合程序要求等。例如,用戶(hù)界面要求輸入一個(gè)整數(shù),而用戶(hù)輸入了一個(gè)字符串,或者要求用戶(hù)輸入一個(gè)URL地址,但用戶(hù)輸入的地址語(yǔ)法錯(cuò)誤等。
    ??? 設(shè)備故障:計(jì)算機(jī)硬件設(shè)備有時(shí)也會(huì)出故障,例如打印機(jī)沒(méi)連接好,要求的網(wǎng)頁(yè)沒(méi)有找到等。
    ??? 物理限制:物理設(shè)備本身的限制,例如硬盤(pán)已存滿,內(nèi)存已用完等。
    ??? 代碼錯(cuò)誤:程序員編寫(xiě)的代碼出現(xiàn)錯(cuò)誤,例如從一個(gè)空的堆棧中彈出元素,數(shù)組下標(biāo)為負(fù)數(shù)等。

    ?
    2、if-else形式的異常處理方法
    ?
    ??? 用if-else語(yǔ)句(或switch-case語(yǔ)句)可以發(fā)現(xiàn)異常并做出相應(yīng)處理。例如,在程序中要將一個(gè)文件整個(gè)讀入內(nèi)存,通常的步驟是:
    ??? (1)打開(kāi)文件。
    ??? (2)判斷文件的大小。
    ??? (3)分配內(nèi)存。
    ??? (4)將文件讀入內(nèi)存。
    ??? (5)關(guān)閉文件。
    ??? 在上述的過(guò)程中可能出現(xiàn)很多問(wèn)題,例如:
    ??? (1)文件打不開(kāi)。
    ??? (2)不能決定文件的大小
    ??? (3)內(nèi)存不能分配
    ??? (4)讀入失敗
    ??? (5)文件不能關(guān)閉
    ??? 針對(duì)這些情況,需要在程序中做出相應(yīng)的處理,若用if-else語(yǔ)句,則程序偽碼如下:
    ??? Class ReadFile?
    ??? {
    ????? 初始化 錯(cuò)誤代碼 = 0;
    ????? 打開(kāi)文件;
    ??? if (文件可以打開(kāi))?
    ??? {
    ??????計(jì)算文件的長(zhǎng)度;
    ??????if (文件的長(zhǎng)度可以決定)?
    ????? {
    ??????? 分配內(nèi)存
    ??????? if (有足夠的內(nèi)存)?
    ??????? {
    ???????? ?將文件讀入內(nèi)存
    ??????? ??if (讀入失敗)?
    ??????? ? {
    ??????? ??? 錯(cuò)誤代碼 = "讀入文件時(shí)失敗"
    ?????? ???}
    ????? ? }
    ????? ? else?
    ????? ??? {
    ????? ??????錯(cuò)誤代碼 = "內(nèi)存不足"
    ???? ???? }
    ???? ?? }
    ??????? else?
    ??????? {
    ??????????錯(cuò)誤代碼 = "不能決定文件的大小"
    ??????? }
    ????? 關(guān)閉文件;
    ????? if (文件沒(méi)有關(guān)閉 && 錯(cuò)誤代碼 == 0)
    ????? {
    ?????????錯(cuò)誤代碼 = "文件關(guān)閉失敗"
    ??????}
    ??? }?
    ??? else?
    ??? {
    ???????錯(cuò)誤代碼 = "文件打不開(kāi)"
    ??? }
    ???return錯(cuò)誤代碼
    }

    ??? 用if-else語(yǔ)句方式可以發(fā)現(xiàn)異常并做出相應(yīng)的處理。但是,程序員由于過(guò)多地分析程序中異常情況的發(fā)生情況,在程序中過(guò)多地使用if-else語(yǔ)句,會(huì)使程序員正常的程序設(shè)計(jì)思路受到影響。另外,程序中過(guò)多地使用if-else語(yǔ)句,也會(huì)影響程序的算法思想的可讀性。而且,會(huì)更為重要的是,有些異常情況是不可預(yù)見(jiàn)的。例如計(jì)算機(jī)的連接中斷,打印機(jī)紙張用完等。所以,if-else形式不是處理異常的好的方法.

    ?
    3、 Java的異常處理方法
    ?
    ??? 在Java語(yǔ)言中,用try模塊和catch模塊把程序的正常流程代碼和異常處理代碼分離。
    ??? 對(duì)于上述例子,按照J(rèn)ava的異常處理方式,偽碼表示的程序代碼如下:
    ??? Class ReadFile
    ??? {
    ????? try?
    ????? {
    ??????? 打開(kāi)文件
    ??????? 計(jì)算文件的長(zhǎng)度
    ??????? 分配內(nèi)存
    ??????? 將文件讀入內(nèi)存
    ??????? 關(guān)閉文件
    ????? }
    ????? catch (文件打開(kāi)失敗異常)?
    ????? {
    ??????? 處理文件打開(kāi)失敗異常
    ????? }?
    ????? catch (文件的長(zhǎng)度不能確定異常)?
    ????? {
    ????? 處理文件的長(zhǎng)度不能確定異常
    ??????}?
    ????? catch (分配內(nèi)存失敗異常)
    ????? {
    ????? 處理分配內(nèi)存失敗異常
    ????? }?
    ????? catch (文件讀入內(nèi)存失敗異常)?
    ????? {
    ????? 處理文件讀入內(nèi)存失敗異常
    ????? }?
    ????? catch (關(guān)閉文件失敗異常)?
    ????? {
    ????? 處理關(guān)閉文件失敗異常
    ????? }
    ????? }

    ??? 從上述偽碼可以看出,程序中可能出現(xiàn)的異常情況都放進(jìn)了try模塊中,而對(duì)于各種異常情況,設(shè)計(jì)了相應(yīng)的catch模塊,這些模塊可以用來(lái)捕捉這些異常情況,并進(jìn)行相應(yīng)的處理。
    ??? 在Java程序中,如果設(shè)計(jì)人員對(duì)可能出現(xiàn)的異常沒(méi)有設(shè)計(jì)相應(yīng)的try模塊和catch模塊,或設(shè)計(jì)人員無(wú)法預(yù)見(jiàn)的異常情況,系統(tǒng)會(huì)將出現(xiàn)的異常交由Java虛擬機(jī)(JVM)處理,此時(shí)Java虛擬機(jī)會(huì)自動(dòng)捕捉這些異常情況,并將異常情況在屏幕上顯示出來(lái)。
    ?
    ?
    2、Java的異常類(lèi)
    ?
    ??? Java語(yǔ)言對(duì)大多數(shù)常見(jiàn)的異常都定義了異常類(lèi)。這些異常類(lèi)可以分為兩大類(lèi):Error類(lèi)Exception類(lèi)
    ??? Error(錯(cuò)誤)類(lèi)和Exception (異常)類(lèi)的區(qū)別在于:錯(cuò)誤指的是系統(tǒng)異常或運(yùn)行環(huán)境出現(xiàn)的異常,這些異常一般是很?chē)?yán)重的異常,即使捕捉到通常也無(wú)法處理,例如Java虛擬機(jī)異常。而Exception類(lèi)的異常指的是一般的異常,例如,輸入/輸出(I/O)異常、數(shù)據(jù)庫(kù)訪問(wèn)(SQL)異常等。對(duì)這些異常應(yīng)用程序可以進(jìn)行處理。Java的所有異常類(lèi)都繼承自Throwable類(lèi)。異常類(lèi)是Java語(yǔ)言包(java.lang)中的類(lèi)。
    ??? Java異常類(lèi)的繼承關(guān)系如圖所示:
    ??? java4-1.gif
    ?
    1、Error類(lèi)及其子類(lèi)
    ?
    ??? 當(dāng)系統(tǒng)動(dòng)態(tài)連接失敗,或者出現(xiàn)虛擬機(jī)的其他故障時(shí),Java虛擬機(jī)會(huì)拋出Error錯(cuò)誤。程序一般不用捕捉Error錯(cuò)誤,由系統(tǒng)進(jìn)行這類(lèi)錯(cuò)誤的捕捉和處理。Error類(lèi)及其子類(lèi)定義了系統(tǒng)中大多數(shù)這類(lèi)錯(cuò)誤。
    ??? 這里介紹Error類(lèi)的兩個(gè)子類(lèi)及其子類(lèi):LinkageError(結(jié)合錯(cuò)誤)類(lèi)及其子類(lèi)和VirtualMachineErrror(虛擬機(jī)錯(cuò)誤)類(lèi)及其子類(lèi)。
    (1)LinkageError類(lèi)及其子類(lèi)
    ??? LinkageError(結(jié)合錯(cuò)誤)類(lèi)及其子類(lèi)定義的是一個(gè)類(lèi)依存于另一個(gè)類(lèi),但在編譯前者時(shí)后者出現(xiàn)了與前者不兼容情況的各種錯(cuò)誤。
    ??? LinkageError類(lèi)的子類(lèi)有:
    ????? ClassFormatError?????? 類(lèi)格式錯(cuò)誤
    ????? ClassCircularityError??類(lèi)循環(huán)錯(cuò)誤
    ????? NoClassDefFoundError??類(lèi)定義無(wú)法找到錯(cuò)誤
    ????? VerifyError??????????? 校驗(yàn)錯(cuò)誤
    ????? AbstractMethodError? ??抽象方法錯(cuò)誤
    ????? NoSuchFieldError?????? 沒(méi)有成員變量錯(cuò)誤
    ????? InstantiationError????實(shí)例錯(cuò)誤
    (2)VirtualMachineErrror類(lèi)及其子類(lèi)
    ??? VirtualMachineErrror(虛擬機(jī)錯(cuò)誤)類(lèi)及其子類(lèi)定義的是系統(tǒng)在虛擬機(jī)損壞或需要運(yùn)行程序的資源耗盡時(shí)出現(xiàn)的各種錯(cuò)誤。
    ??? VirtualMachineErrror類(lèi)的子類(lèi)有:
    ????? InternalError ??????內(nèi)部錯(cuò)誤
    ????? OutOfMemoryError????內(nèi)存溢出錯(cuò)誤
    ????? StackOverflowError??堆棧溢出錯(cuò)誤
    ????? UnkownError???????? 未知錯(cuò)誤
    ?
    2Exception類(lèi)及其子類(lèi)
    ?
    ??? Exception類(lèi)及其子類(lèi)定義了程序中大多數(shù)可以處理的異常。
    ??? 這里介紹Exception類(lèi)的兩個(gè)子類(lèi)及其子類(lèi):RuntimeException (運(yùn)行時(shí)異常)類(lèi)及其子類(lèi)和CheckedException (檢查異常) 類(lèi)及其子類(lèi)。
    (1)RuntimeException類(lèi)及其子類(lèi)
    ??? RuntimeException(運(yùn)行時(shí)異常)類(lèi)及其子類(lèi)定義的是Java程序執(zhí)行過(guò)程中可能出現(xiàn)的各種異常,RuntimeException類(lèi)的子類(lèi)有:
    ????? ArithmeticException???????????? 算術(shù)運(yùn)算異常
    ????? ArrayStoreException???????????? 數(shù)組存儲(chǔ)異常
    ????? ArrayIndexOutOfBoundsException??數(shù)組下標(biāo)越界異常
    ????? CaseCastException???????????????類(lèi)型轉(zhuǎn)換異常
    ????? IllegalArgumentException????????非法參數(shù)異常
    ????? IllegalThreadStateException?????非法線程狀態(tài)異常
    ????? NumberFormatException?????????? 數(shù)字格式異常
    ????? IlegalMonitorStateException?????非法監(jiān)視狀態(tài)異常
    ????? IndexOutofBoundsException??????下標(biāo)超出范圍異常
    ????? NegativeArraySizeEXception?????負(fù)數(shù)組個(gè)數(shù)異常
    ????? NullPointerException??????????? 空指針異常
    ????? SecurityException?????????????? 安全異常
    ????? EmptyStackException???????????? 空棧異常
    ????? NoSuchElementException????????? 沒(méi)有元素異常
    (2)CheckedException 及其子類(lèi)
    ??? CheckedException (檢查異常)類(lèi)及其子類(lèi)定義的是Java程序編譯時(shí)編譯器發(fā)現(xiàn)的各種異常。
    ??? CheckedException類(lèi)的子類(lèi)有:
    ????? ClassNotFoundException???????類(lèi)找不到異常
    ????? CloneNotSupportedException???復(fù)制不支持異常
    ????? IllegalAccessException ??????非法訪問(wèn)異常
    ????? InstantiationException ??????實(shí)例異常
    ????? InterruptedException???????? 中斷異常
    ????? IOException????????????????? 輸入/輸出異常
    ????? FileNotFoundException???????文件找不到異常
    ????? InterruptedIOException ??????中斷輸入/輸出異常
    ?
    3Throwable類(lèi)的方法
    ?
    ??? Error類(lèi)和Exception類(lèi)的方法基本都是從Throwable類(lèi)中繼承來(lái)的。
    ??? Throwable類(lèi)的構(gòu)造方法主要有:
    ????? Throwable()?????????????? //構(gòu)造一個(gè)對(duì)象,其錯(cuò)誤信息串為null
    ????? Throwable(String message)?//構(gòu)造一個(gè)對(duì)象,其錯(cuò)誤信息串為message
    ??? Throwable類(lèi)的方法主要有:
    ????? String getMessage()???????返回對(duì)象的錯(cuò)誤信息
    ????? void printStackTrace()???輸出對(duì)象的跟蹤信息到標(biāo)準(zhǔn)錯(cuò)誤輸出流
    ????? void printStackTrace(PrintStream s)? ?輸出對(duì)象的跟蹤信息到輸出流s
    ????? String toString()???????? 返回對(duì)象的簡(jiǎn)短描述信息

    ?
    4、異常類(lèi)的對(duì)象
    ?
    ??? 應(yīng)用程序中一旦出現(xiàn)異常,系統(tǒng)會(huì)產(chǎn)生一個(gè)異常類(lèi)的對(duì)象,下面討論的catch語(yǔ)句后面的參數(shù)將接收到這樣的一個(gè)對(duì)象。
    ??? 為了語(yǔ)言簡(jiǎn)潔,通常把異常類(lèi)的對(duì)象也簡(jiǎn)稱(chēng)異常。這就像第6章中我們也把組件類(lèi)的對(duì)象簡(jiǎn)稱(chēng)組件。
    ?
    ?
    3、Java的異常處理方法
    ?
    ??? 在Java程序中,用try-catch(或try-catch-finally)語(yǔ)句來(lái)拋出、捕捉和處理異常。
    ??? try-catch-finally語(yǔ)句的語(yǔ)法格式是:
    ??? try
    ??? {
    ????? 可能拋出異常的語(yǔ)句模塊;
    ??? }
    ?
    ??? catch?(異常類(lèi)型1)
    ??? {
    ????? 處理異常類(lèi)型1語(yǔ)句;
    ??? }
    ??? ……
    ??? catch?(異常類(lèi)型n)
    ??? {
    ????? 處理異常類(lèi)型n語(yǔ)句;
    ??? }
    ??? finally
    ??? {
    ????? 無(wú)論是否拋出異常都要執(zhí)行的語(yǔ)句;
    ??? }

    try-catch-finally語(yǔ)句的功能為:
    (1)try模塊:
    ??? 所有可能拋出異常的語(yǔ)句都放入try模塊中。try模塊中的語(yǔ)句是程序正常流程要執(zhí)行的語(yǔ)句,但是在執(zhí)行過(guò)程中有可能出現(xiàn)異常。如果像前面程序設(shè)計(jì)例子那樣沒(méi)有使用try模塊,則除了系統(tǒng)定義的異常外,語(yǔ)句執(zhí)行過(guò)程中出現(xiàn)的其他異常不會(huì)被拋出。
    (2)catch模塊:
    ??? 主要負(fù)責(zé)對(duì)拋出的異常做相應(yīng)的處理。所有拋出的異常都必須是Throwable類(lèi)或其子類(lèi)的對(duì)象。try模塊中的語(yǔ)句可能拋出很多不同類(lèi)型的異常,所以需要針對(duì)不同類(lèi)型的異常分別設(shè)計(jì)catch模塊。一般程序中會(huì)有若干個(gè)catch模塊,每一模塊處理一種類(lèi)型的異常。
    ????對(duì)于這些catch模塊,其排列的先后順序有如下規(guī)定:出現(xiàn)在前面的catch模塊中的異常類(lèi)一定要是后面的catch模塊中的異常類(lèi)的子類(lèi), 即前面的catch模塊中的異常類(lèi)對(duì)象一定比后面的catch模塊中的異常類(lèi)對(duì)象特殊。這是因?yàn)閏atch模塊是按順序執(zhí)行的。如果try模塊拋出異常,系統(tǒng)會(huì)按catch模塊的排列次序依次查找,如果前面catch模塊的異常類(lèi)型匹配不上,就按順序和后面的catch模塊匹配。如果在所有的catch模塊中都匹配不上,就交給系統(tǒng)的虛擬機(jī),由虛擬機(jī)來(lái)處理這個(gè)異常。
    ??? 程序中即使沒(méi)有try模塊,若出現(xiàn)了系統(tǒng)定義的異常,系統(tǒng)也會(huì)自動(dòng)拋出,并由系統(tǒng)負(fù)責(zé)捕捉和處理;但是程序中若有了catch模塊,則一定要有try模塊。另外,若用戶(hù)希望按照自己的意圖處理程序中可能出現(xiàn)的系統(tǒng)定義的異常,也要在程序中使用try-catch語(yǔ)句,否則出現(xiàn)的異常將由系統(tǒng)捕捉和處理。
    (3)finally模塊:
    ??? finally模塊中的語(yǔ)句是必須執(zhí)行的語(yǔ)句。無(wú)論try模塊中是否拋出異常,finally模塊中的語(yǔ)句時(shí)都要被執(zhí)行。這個(gè)模塊是可選的。如果設(shè)計(jì)了finally模塊,通常在這個(gè)模塊中做一些資源回收的工作。
    ?
    【例8.1】try-catch-finally的執(zhí)行過(guò)程示例。
    要求:設(shè)計(jì)一個(gè)用命令行參數(shù)輸入數(shù)據(jù)的程序,若該參數(shù)的數(shù)值輸入的不正確會(huì)出現(xiàn)異常。
    程序設(shè)計(jì)如下:
    public class TryCatchSequence
    {
    ?? public static void main(String args[])
    ?? {
    ????? int a,b,c;
    ????? try
    ????? {??
    ???????? a=100;
    ???????? b=Integer.parseInt(args[0]);??????????? //把命令行輸入的字符串轉(zhuǎn)換成整數(shù)
    ???????? c=a/b;
    ???????? System.out.println("c="+c);??????
    ???????? System.out.println("No exception.");?????????
    ????? }
    ????? catch(ArrayIndexOutOfBoundsException e)??? //數(shù)組下標(biāo)越界異常
    ????? {
    ???????? System.out.println("Exception caught!");
    ???????? e.printStackTrace();
    ????? }
    ????? catch(ArithmeticException e)???????????????//處理算術(shù)運(yùn)算異常
    ????? {
    ???????? System.out.println("Exception caught!");
    ???????? e.printStackTrace();
    ????? }
    ????? finally
    ????? {
    ???????? System.out.println("Always executed");
    ????? }
    ?? }
    }

    我們分以下幾種情況分別運(yùn)行上述程序:
    (1) 沒(méi)有異常拋出。在當(dāng)前工作目錄下鍵入如下命令(注意:該程序正常運(yùn)行需要從命令行給出參數(shù),且該參數(shù)值不能為0):
    java TryCatchSequence 10
    則程序的運(yùn)行結(jié)果如下:
    c=10
    No exception.
    Always executed
    程序的運(yùn)行結(jié)果說(shuō)明:系統(tǒng)執(zhí)行完了try模塊的所有程序, 由于程序運(yùn)行時(shí)沒(méi)有異常拋出,所以系統(tǒng)跳過(guò)catch模塊, 最后執(zhí)行了finally模塊。
    (2) 有異常拋出。上述程序可能有如下兩種類(lèi)型的異常發(fā)生。
    --拋出數(shù)組下標(biāo)越界異常。
    在當(dāng)前工作目錄下鍵入如下命令(注意:該程序運(yùn)行時(shí)無(wú)法從命令行得到參數(shù)值):
    java TryCatchSequence
    程序運(yùn)行結(jié)果如下:
    Exception caught!
    java.lang.ArrayIndexOutOfBoundsException: 0
    ??????? at TryCatchSequence.main(TryCatchSequence.java:9)
    Always executed
    程序的運(yùn)行結(jié)果說(shuō)明:由于命令行沒(méi)有給出參數(shù),在執(zhí)行語(yǔ)句:
    b=Integer.parseInt(args[0]);
    時(shí),系統(tǒng)拋出了數(shù)組下標(biāo)越界異常。程序中處理數(shù)組下標(biāo)越界異常的catch模塊匹配上了該異常。程序執(zhí)行完該catch模塊語(yǔ)句后,跳過(guò)后面的其它c(diǎn)atch模塊,又執(zhí)行了finally模塊中的語(yǔ)句。
    --拋出算術(shù)運(yùn)算異常。
    在當(dāng)前工作目錄下鍵入如下命令(注意:該程序運(yùn)行時(shí)從命令行得到的參數(shù)值為0):
    java TryCatchSequence 0
    程序運(yùn)行結(jié)果如下:
    Exception caught!
    java.lang.ArithmeticException: / by zero
    ??????? at TryCatchSequence.main(TryCatchSequence.java:10)
    Always executed
    程序的運(yùn)行結(jié)果說(shuō)明:由于命令行給出的參數(shù)為0,程序中的被除數(shù)為0,因此運(yùn)行時(shí)系統(tǒng)拋出了算術(shù)運(yùn)算異常。程序中處理算術(shù)運(yùn)算異常的catch模塊匹配上了該異常。程序執(zhí)行完該catch模塊語(yǔ)句后,跳過(guò)后面的其它c(diǎn)atch模塊,又執(zhí)行了finally模塊中的語(yǔ)句。
    ?
    【例8.2】程序中設(shè)計(jì)的catch模塊捕捉不到異常的示例。
    要求:程序中設(shè)計(jì)了若干catch模塊,但忽略了其中某種可能發(fā)生的異常。
    程序設(shè)計(jì)如下:
    public class TryCatchSequence1
    {
    ?? public static void main(String args[])
    ?? {
    ????? int a,b,c;
    ????? try
    ????? {??
    ????????? a=100;
    ????????? b=Integer.parseInt(args[0]);
    ????????? c=a/b;
    ????????? System.out.println("c="+c);??????
    ????????? System.out.println("No exception.");?????????
    ????? }
    ????? catch(ArithmeticException e)
    ????? {
    ????????? System.out.println("Exception caught!");
    ????????? e.printStackTrace();
    ????? }
    ????? finally
    ????? {
    ? ???? System.out.println("Always executed");
    ????? }
    ?? }
    }
    程序設(shè)計(jì)說(shuō)明:上述程序和例8.1的程序基本相同,只是去掉了前面程序的catch(ArrayIndexOutOfBoundsException e)模塊。
    程序運(yùn)行結(jié)果如下:
    Always executed
    Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
    ??????? at TryCatchSequence2.main(TryCatchSequence2.java:9)
    程序的運(yùn)行結(jié)果說(shuō)明:程序中出現(xiàn)的ArrayIndexOutOfBoundsException異常不能和程序中的任何catch模塊匹配,因此交給系統(tǒng)處理,系統(tǒng)內(nèi)置的異常處理模塊輸出了相應(yīng)的錯(cuò)誤信息。
    ?
    ?
    4、異常的拋出和處理
    ?
    ??? 系統(tǒng)的異常類(lèi)定義了很多異常,如果程序運(yùn)行時(shí)出現(xiàn)了系統(tǒng)定義的異常,系統(tǒng)會(huì)自動(dòng)拋出。此時(shí),若應(yīng)用程序中有try-catch語(yǔ)句,則這些異常由系統(tǒng)捕捉并交給應(yīng)用程序處理;若應(yīng)用程序中沒(méi)有try-catch語(yǔ)句,則這些異常由系統(tǒng)捕捉和處理。
    ??? 對(duì)于系統(tǒng)定義的有些應(yīng)用程序可以處理的異常,一般情況下并不希望由系統(tǒng)來(lái)捕捉和處理,也不希望這種異常造成后果,因?yàn)檫@兩種情況都有可能造成運(yùn)行的應(yīng)用程序產(chǎn)生不良后果。這種情況下,設(shè)計(jì)應(yīng)用程序的一般方法是:在try模塊中,應(yīng)用程序自己判斷是否有異常出現(xiàn),如果有異常出現(xiàn),則創(chuàng)建異常對(duì)象并用throw語(yǔ)句拋出該異常對(duì)象;在catch模塊中,設(shè)計(jì)用戶(hù)自己希望的異常處理方法。
    ??? throw語(yǔ)句的語(yǔ)法格式為:
    ??? throw <異常類(lèi)對(duì)象>;?
    ??? 這種情況下,異常的拋出和處理有兩種方式:一種是在同一個(gè)方法中拋出異常和處理異常,另一種是在一個(gè)方法中拋出異常,在調(diào)用該方法的方法中處理異常。

    ?
    1、在同一個(gè)方法中拋出異常和處理異常
    ?
    ??? 在同一個(gè)方法中拋出異常和處理異常。應(yīng)用程序中,大部分異常的拋出和異常的處理采用這種設(shè)計(jì)方法。
    ?
    【例8.3】在同一個(gè)方法中拋出異常和處理異常示例。
    要求:設(shè)計(jì)一個(gè)堆棧類(lèi),堆棧類(lèi)中要求有一個(gè)入棧方法,該方法向堆棧中加入一個(gè)元素。當(dāng)調(diào)用入棧方法且堆棧已滿時(shí)會(huì)出現(xiàn)堆棧已滿異常。處理異常的模塊捕捉到該異常后,顯示異常信息后退出系統(tǒng)。
    程序設(shè)計(jì)如下:
    class SeqStack????//堆棧類(lèi)
    {
    ?int data[];??????//成員變量,存放元素
    ?int MAX; ????????//成員變量,數(shù)組個(gè)數(shù)
    ?int top;????????//成員變量,當(dāng)前元素個(gè)數(shù)
    ?
    ?SeqStack(int m)?//構(gòu)造方法
    ?{
    ??MAX = m;???????//為MAX賦值m
    ??data = new int[MAX];????//創(chuàng)建數(shù)組對(duì)象data
    ??top = 0; ???????//初始值為0
    ?}
    ?
    ?public void push(int item)????//入棧方法
    ?{
    ??try?????????//try模塊
    ??{
    ???if(top == MAX)?????? //判斷是否有異常產(chǎn)生
    ????throw new Exception("stackFull");?//拋出異常對(duì)象
    ???data[top] = item;????//在堆棧中加入元素item
    ???top++;???????//元素個(gè)數(shù)加1
    ??}????
    ??catch(Exception e) ?????//catch模塊
    ??{
    ???System.out.println("exception:"+e.getMessage());
    ???System.exit(0);
    ??}?
    ?}
    ?
    ?public static void main(String args[])
    ?{
    ?? ??SeqStack stack = new SeqStack(10);??//創(chuàng)建對(duì)象stack
    ?? ??for(int i = 0; i <11; i++)
    ?????stack.push(i);??????//調(diào)用push()方法
    ?}????
    }
    程序運(yùn)行結(jié)果如下:
    exception:stackFull

    程序設(shè)計(jì)說(shuō)明:
    (1)main()中第一條語(yǔ)句創(chuàng)建的對(duì)象stack的數(shù)組個(gè)數(shù)MAX為10,但循環(huán)語(yǔ)句最后一次執(zhí)行時(shí),要向?qū)ο髎tack的數(shù)組data中加入第11個(gè)元素,所以此時(shí)會(huì)產(chǎn)生異常。
    (2)由于push()方法中的異常情況(top == MAX)不是系統(tǒng)定義的異常,所以,系統(tǒng)不會(huì)拋出該異常,需要在該方法中用throw語(yǔ)句自己拋出異常。
    (3)拋出異常語(yǔ)句throw new Exception("stackFull")首先調(diào)用Exception類(lèi)的構(gòu)造方法創(chuàng)建一個(gè)異常信息為"stackFull"的異常對(duì)象,然后拋出該異常。
    (4)push()方法中的catch模塊捕捉到異常后進(jìn)行了所要求的異常處理。
    ?
    2、拋出異常和處理異常的方法不是同一個(gè)

    ??? 如果拋出異常的方法和處理異常的方法不是同一個(gè)方法時(shí),則要求在拋出異常的方法定義后加如下語(yǔ)句:
    ??? throws Exception
    ??? 然后,把catch模塊放在調(diào)用該方法的方法中。
    ??? throws Exception語(yǔ)句的功能,是在調(diào)用方法和可能產(chǎn)生異常的被調(diào)用方法之間建立起系統(tǒng)處理異常所需的聯(lián)系。
    ?
    【例8.4】拋出異常和處理異常的方法不是同一個(gè)示例。
    要求:?jiǎn)栴}同例8.3,但要求拋出異常和處理異常的方法不是同一個(gè)。
    程序設(shè)計(jì)如下:
    class SeqStack2
    {
    ?int data[];?
    ?int MAX;
    ?int top;?
    ?
    ?SeqStack2(int m)??
    ?{
    ??MAX = m;
    ??data = new int[MAX];
    ??top = 0;
    ?}
    ?
    ?public void push(int item) throws Exception?//加throws語(yǔ)句
    ?{
    ??if(top == MAX) ???????//判斷是否有異常產(chǎn)生
    ???throw new Exception("stackFull");?//拋出異常
    ??data[top] = item;
    ??top++;
    ?}
    ?
    ?public static void main(String args[])
    ?{??
    ?? ??SeqStack2 stack = new SeqStack2(10);
    ?? ??try??????????//try模塊
    ?? ??{
    ?? ???for(int i = 0; i <11; i++)
    ?? ????stack.push(i);
    ?? ??}
    ??catch(Exception e)??????//catch模塊
    ??{
    ???System.out.println("exception:"+e.getMessage());
    ???System.exit(0);
    ??}??? ???
    ?}????
    }
    程序運(yùn)行結(jié)果和例8.3相同。

    ??? 需要說(shuō)明的是,此例子只是為了說(shuō)明此種設(shè)計(jì)方法,像例8.3這類(lèi)問(wèn)題應(yīng)用程序的異常拋出和異常處理通常采用前一種設(shè)計(jì)方法。
    ??? 但是,Java API中的許多可能出現(xiàn)異常的方法都采用此種設(shè)計(jì)方法。例如,第9章討論的輸入輸出流類(lèi)中的許多方法在調(diào)用時(shí)都可能出現(xiàn)異常,而調(diào)用這些方法的方法是在用戶(hù)編寫(xiě)的應(yīng)用程序中,Java API不可能設(shè)計(jì)出適合所有應(yīng)用情況的異常處理方法,因此,Java API的這些方法中沒(méi)有設(shè)計(jì)try模塊和catch模塊,只是在方法定義后添加了throws語(yǔ)句。如下方法定義就是一個(gè)例子:
    ??? public void close()? throws IOException
    ????????? //表示close()方法可能拋出IOException異常
    ??? 如果應(yīng)用程序調(diào)用該方法,一般情況下,要在調(diào)用方法中設(shè)計(jì)try模塊和catch模塊,來(lái)處理IOException異常。IOException類(lèi)是Exception類(lèi)的一個(gè)子類(lèi)。

    ?
    ?
    5、自定義的異常類(lèi)

    ??? 應(yīng)用程序中除了可能出現(xiàn)系統(tǒng)定義的異常外,有時(shí)還可能出現(xiàn)系統(tǒng)沒(méi)有考慮的異常。此時(shí)需要在應(yīng)用程序中自定義異常類(lèi)。一般情況下,自定義的異常類(lèi)都是一些應(yīng)用程序可以處理的異常。所以,自定義的異常類(lèi)一般是Exception類(lèi)的子類(lèi)。
    ?
    【例8.5】自定義的異常類(lèi)示例。
    class UserDefinedException extends Exception
    {
    ?? String? msg;
    ?? public UserDefinedException()???????
    ?? {
    ????? this.msg = "";
    ?? }
    ?? public UserDefinedException(String s)????????
    ?? {
    ????? this.msg = s;
    ?? }???
    }

    例8.5中,用戶(hù)自己定義的異常類(lèi)UserDefinedException繼承了類(lèi)Exception,類(lèi)UserDefinedException中定義了兩種情況的異常,一種的參數(shù)為空,另一種的參數(shù)為字符串s。




    -The End-

    posted on 2008-09-25 20:20 decode360-3 閱讀(980) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): Java
    主站蜘蛛池模板: 亚洲综合图片小说区热久久| 中文字幕亚洲乱码熟女一区二区 | 美丽姑娘免费观看在线观看中文版| 亚洲欧洲自拍拍偷精品 美利坚| 无遮挡呻吟娇喘视频免费播放| 亚洲欧洲一区二区三区| 免费人成视频在线观看免费| 日本牲交大片免费观看| 国产成人精品久久亚洲高清不卡| 国产男女性潮高清免费网站| 国产精品亚洲天堂| 亚洲男人天堂2020| a级成人毛片免费视频高清| 亚洲欧洲日产国码久在线观看| 1000部羞羞禁止免费观看视频| 亚洲欧洲久久精品| 在线观看人成网站深夜免费| 亚洲AV无码一区二区三区牲色| 四虎AV永久在线精品免费观看| 人妻18毛片a级毛片免费看| 亚洲AV无码国产在丝袜线观看| 久久久久久曰本AV免费免费| 亚洲人成77777在线播放网站不卡| 99精品全国免费观看视频| 精品在线免费视频| 精品国产亚洲一区二区三区| 67194国产精品免费观看| 亚洲人成网站在线播放2019| heyzo亚洲精品日韩| 91青青青国产在观免费影视| 亚洲欧美日韩自偷自拍| 久久精品国产亚洲Aⅴ香蕉| 69精品免费视频| 精品成人一区二区三区免费视频| 亚洲精品无码久久久久去q | 亚洲黄色网址大全| 午夜精品在线免费观看| 日本道免费精品一区二区| 亚洲AV一二三区成人影片| 亚洲国产精品激情在线观看| 91精品国产免费|