Decode360's Blog

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

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 ::  :: 管理 ::
            397 隨筆 :: 33 文章 :: 29 評論 :: 0 Trackbacks
          Java學(xué)習(xí)(四).異常處理

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

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

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

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

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

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

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

          try-catch-finally語句的功能為:
          (1)try模塊:
          ??? 所有可能拋出異常的語句都放入try模塊中。try模塊中的語句是程序正常流程要執(zhí)行的語句,但是在執(zhí)行過程中有可能出現(xiàn)異常。如果像前面程序設(shè)計例子那樣沒有使用try模塊,則除了系統(tǒng)定義的異常外,語句執(zhí)行過程中出現(xiàn)的其他異常不會被拋出。
          (2)catch模塊:
          ??? 主要負(fù)責(zé)對拋出的異常做相應(yīng)的處理。所有拋出的異常都必須是Throwable類或其子類的對象。try模塊中的語句可能拋出很多不同類型的異常,所以需要針對不同類型的異常分別設(shè)計catch模塊。一般程序中會有若干個catch模塊,每一模塊處理一種類型的異常。
          ??? 對于這些catch模塊,其排列的先后順序有如下規(guī)定:出現(xiàn)在前面的catch模塊中的異常類一定要是后面的catch模塊中的異常類的子類, 即前面的catch模塊中的異常類對象一定比后面的catch模塊中的異常類對象特殊。這是因?yàn)閏atch模塊是按順序執(zhí)行的。如果try模塊拋出異常,系統(tǒng)會按catch模塊的排列次序依次查找,如果前面catch模塊的異常類型匹配不上,就按順序和后面的catch模塊匹配。如果在所有的catch模塊中都匹配不上,就交給系統(tǒng)的虛擬機(jī),由虛擬機(jī)來處理這個異常。
          ??? 程序中即使沒有try模塊,若出現(xiàn)了系統(tǒng)定義的異常,系統(tǒng)也會自動拋出,并由系統(tǒng)負(fù)責(zé)捕捉和處理;但是程序中若有了catch模塊,則一定要有try模塊。另外,若用戶希望按照自己的意圖處理程序中可能出現(xiàn)的系統(tǒng)定義的異常,也要在程序中使用try-catch語句,否則出現(xiàn)的異常將由系統(tǒng)捕捉和處理。
          (3)finally模塊:
          ??? finally模塊中的語句是必須執(zhí)行的語句。無論try模塊中是否拋出異常,finally模塊中的語句時都要被執(zhí)行。這個模塊是可選的。如果設(shè)計了finally模塊,通常在這個模塊中做一些資源回收的工作。
          ?
          【例8.1】try-catch-finally的執(zhí)行過程示例。
          要求:設(shè)計一個用命令行參數(shù)輸入數(shù)據(jù)的程序,若該參數(shù)的數(shù)值輸入的不正確會出現(xiàn)異常。
          程序設(shè)計如下:
          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) 沒有異常拋出。在當(dāng)前工作目錄下鍵入如下命令(注意:該程序正常運(yùn)行需要從命令行給出參數(shù),且該參數(shù)值不能為0):
          java TryCatchSequence 10
          則程序的運(yùn)行結(jié)果如下:
          c=10
          No exception.
          Always executed
          程序的運(yùn)行結(jié)果說明:系統(tǒng)執(zhí)行完了try模塊的所有程序, 由于程序運(yùn)行時沒有異常拋出,所以系統(tǒng)跳過catch模塊, 最后執(zhí)行了finally模塊。
          (2) 有異常拋出。上述程序可能有如下兩種類型的異常發(fā)生。
          --拋出數(shù)組下標(biāo)越界異常。
          在當(dāng)前工作目錄下鍵入如下命令(注意:該程序運(yùn)行時無法從命令行得到參數(shù)值):
          java TryCatchSequence
          程序運(yùn)行結(jié)果如下:
          Exception caught!
          java.lang.ArrayIndexOutOfBoundsException: 0
          ??????? at TryCatchSequence.main(TryCatchSequence.java:9)
          Always executed
          程序的運(yùn)行結(jié)果說明:由于命令行沒有給出參數(shù),在執(zhí)行語句:
          b=Integer.parseInt(args[0]);
          時,系統(tǒng)拋出了數(shù)組下標(biāo)越界異常。程序中處理數(shù)組下標(biāo)越界異常的catch模塊匹配上了該異常。程序執(zhí)行完該catch模塊語句后,跳過后面的其它c(diǎn)atch模塊,又執(zhí)行了finally模塊中的語句。
          --拋出算術(shù)運(yùn)算異常。
          在當(dāng)前工作目錄下鍵入如下命令(注意:該程序運(yùn)行時從命令行得到的參數(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é)果說明:由于命令行給出的參數(shù)為0,程序中的被除數(shù)為0,因此運(yùn)行時系統(tǒng)拋出了算術(shù)運(yùn)算異常。程序中處理算術(shù)運(yùn)算異常的catch模塊匹配上了該異常。程序執(zhí)行完該catch模塊語句后,跳過后面的其它c(diǎn)atch模塊,又執(zhí)行了finally模塊中的語句。
          ?
          【例8.2】程序中設(shè)計的catch模塊捕捉不到異常的示例。
          要求:程序中設(shè)計了若干catch模塊,但忽略了其中某種可能發(fā)生的異常。
          程序設(shè)計如下:
          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è)計說明:上述程序和例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é)果說明:程序中出現(xiàn)的ArrayIndexOutOfBoundsException異常不能和程序中的任何catch模塊匹配,因此交給系統(tǒng)處理,系統(tǒng)內(nèi)置的異常處理模塊輸出了相應(yīng)的錯誤信息。
          ?
          ?
          4、異常的拋出和處理
          ?
          ??? 系統(tǒng)的異常類定義了很多異常,如果程序運(yùn)行時出現(xiàn)了系統(tǒng)定義的異常,系統(tǒng)會自動拋出。此時,若應(yīng)用程序中有try-catch語句,則這些異常由系統(tǒng)捕捉并交給應(yīng)用程序處理;若應(yīng)用程序中沒有try-catch語句,則這些異常由系統(tǒng)捕捉和處理。
          ??? 對于系統(tǒng)定義的有些應(yīng)用程序可以處理的異常,一般情況下并不希望由系統(tǒng)來捕捉和處理,也不希望這種異常造成后果,因?yàn)檫@兩種情況都有可能造成運(yùn)行的應(yīng)用程序產(chǎn)生不良后果。這種情況下,設(shè)計應(yīng)用程序的一般方法是:在try模塊中,應(yīng)用程序自己判斷是否有異常出現(xiàn),如果有異常出現(xiàn),則創(chuàng)建異常對象并用throw語句拋出該異常對象;在catch模塊中,設(shè)計用戶自己希望的異常處理方法。
          ??? throw語句的語法格式為:
          ??? throw <異常類對象>;?
          ??? 這種情況下,異常的拋出和處理有兩種方式:一種是在同一個方法中拋出異常和處理異常,另一種是在一個方法中拋出異常,在調(diào)用該方法的方法中處理異常。

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

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

          ??? 如果拋出異常的方法和處理異常的方法不是同一個方法時,則要求在拋出異常的方法定義后加如下語句:
          ??? throws Exception
          ??? 然后,把catch模塊放在調(diào)用該方法的方法中。
          ??? throws Exception語句的功能,是在調(diào)用方法和可能產(chǎn)生異常的被調(diào)用方法之間建立起系統(tǒng)處理異常所需的聯(lián)系。
          ?
          【例8.4】拋出異常和處理異常的方法不是同一個示例。
          要求:問題同例8.3,但要求拋出異常和處理異常的方法不是同一個。
          程序設(shè)計如下:
          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語句
          {
          ? 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相同。

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

          ?
          ?
          5、自定義的異常類

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

          例8.5中,用戶自己定義的異常類UserDefinedException繼承了類Exception,類UserDefinedException中定義了兩種情況的異常,一種的參數(shù)為空,另一種的參數(shù)為字符串s。
          posted on 2008-09-25 20:20 decode360 閱讀(247) 評論(0)  編輯  收藏 所屬分類: 04.Java

          只有注冊用戶登錄后才能發(fā)表評論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 贞丰县| 阳原县| 墨竹工卡县| 介休市| 辽宁省| 南部县| 建平县| 绥德县| 灵石县| 高邮市| 隆尧县| 涡阳县| 项城市| 丹寨县| 庄浪县| 错那县| 威信县| 弥勒县| 兴业县| 沅陵县| 仪征市| 内黄县| 分宜县| 交城县| 三都| 陇川县| 滕州市| 关岭| 岗巴县| 揭西县| 开鲁县| 日喀则市| 祁门县| 定结县| 明水县| 安仁县| 洱源县| 共和县| 司法| 娄烦县| 锡林浩特市|