最近遇到有關(guān)ERROR的處理問題,下面這篇文章
轉(zhuǎn)至:http://www.cnblogs.com/deepnighttwo/archive/2006/12/11/1964305.html
LinkageError是一個比較棘手的異常,準確的說它是一個Error而不是Exception。java api對它沒有直接的解釋,而是介紹了它的子類:
Subclasses of LinkageError indicate that a class has some dependency on another class; however, the latter class has incompatibly changed after the compilation of the former class.
public class Test24 { public static void main(String[] args){ foo1(); } public static void foo1(){ try{ Test01 t1 = new Test01();// throw new RuntimeException(); }catch(Exception e){ System.out.println("111111111"); //e.printStackTrace(); }finally{ System.out.println("222222222"); } System.out.println("333333333"); int i=0; i++; System.out.println(i); }}
所以雖然可以捕獲這些錯誤,用 catch(Throwable e) 的方式,但還是不建議這么做,業(yè)務(wù)代碼還是 catch (Exception e) ,
異常的處理主要包括捕獲異常、程序流程的跳轉(zhuǎn)和異常處理語句塊的定義等。當一個異常被拋出時,應(yīng)該有專門的語句來捕獲這個被拋出的異常對象,這個過程被稱為捕獲異常。當一個異常類的對象被捕獲后,用戶程序就會發(fā)生流程的跳轉(zhuǎn),系統(tǒng)中止當前的流程而跳轉(zhuǎn)至專門的異常處理語句塊,或直接跳出當前程序和 Java 虛擬機,退回到操作系統(tǒng)。
Java 中所有的異常都由類來表示。所有的異常都是從一個名為 Throwable 的類派生出來的。因此,當程序中發(fā)生一個異常時,就會生成一個異常類的某種類型的對象。 Throwable 類有兩個直接子類: Exception 和 Error 。
與 Error 類型的異常相關(guān)的錯誤發(fā)生在 Java 虛擬機中,而不是在程序中。錯誤類( Error )定義了被認為是不能恢復(fù)的嚴重錯誤條件。在大多數(shù)情況下,當遇到這樣的錯誤時,建議讓該程序中斷。這樣的異常超出了程序可控制的范圍。
由程序運行所導(dǎo)致的錯誤由 Exception 類來表示,該異常類定義了程序中可能遇到的輕微的錯誤條件??梢跃帉懘a來處理這樣的異常并繼續(xù)執(zhí)行程序,而不是讓程序中斷。它代表輕微的可以恢復(fù)的故障。接收到異常信號后,調(diào)用方法捕獲拋出的異常,在可能的情況下再恢復(fù)回來,這樣程序員可以通過處理程序來處理異常。
Java 中的異常類具有層次組織,其中 Throwable 類是 Error 類(錯誤類)和 Exception 類(異常類)的父類, Throwable 類是 Object 類的直接子類。
異常類( java.lang.Exception )繼承于 java.lang.Object 類中的 java.lang.Throwable 類。異常可分為執(zhí)行異常( Runtime Exception )和檢查異常( Checked Exception )兩種,如圖 8-1 所示。為了深入了解執(zhí)行異常和檢查異常內(nèi)容,這里給出它們的詳細介紹列舉。
圖 8-1 異常類的繼承結(jié)構(gòu)
執(zhí)行異常即運行時異常,繼承于 Runtime Exception 。 Java 編譯器允許程序不對它們做出處理。下面列出了主要的運行時異常。
· ArithmeticException : 一個非法算術(shù)運算產(chǎn)生的異常。
· ArrayStoreException : 存入數(shù)組的內(nèi)容數(shù)據(jù)類型不一致所產(chǎn)生的異常。
· ArrayIndexOutOfBoundsException : 數(shù)組索引超出范圍所產(chǎn)生的異常。
· ClassCastException : 類對象強迫轉(zhuǎn)換造成不當類對象所產(chǎn)生的異常。
· IllegalArgumentException : 程序調(diào)用時,返回錯誤自變量的數(shù)據(jù)類型。
· IllegalThreadStateException : 線程在不合理狀態(tài)下運行所產(chǎn)生的異常。
· NumberFormatException : 字符串轉(zhuǎn)換為數(shù)值所產(chǎn)生的異常。
· IllegalMonitorStateException : 線程等候或通知對象時所產(chǎn)生的異常。
· IndexOutOfBoundsException : 索引超出范圍所產(chǎn)生的異常。
· NegativeException : 數(shù)組建立負值索引所產(chǎn)生的異常。
· NullPointerException : 對象引用參考值為 null所產(chǎn)生的異常。
· SecurityException : 違反安全所產(chǎn)生的異常。
除了執(zhí)行異常外,其余的子類是屬于檢查異常類也稱為非運行時異常,它們都在 java.lang 類庫內(nèi)定義。 Java 編譯器要求程序必須捕獲或者聲明拋棄這種異常。下面列出了主要的檢查異常。
· ClassNotFoundException : 找不到類或接口所產(chǎn)生的異常。
· CloneNotSupportedException : 使用對象的 clone( )方法但無法執(zhí)行 Cloneable所產(chǎn)生的異常。
· IllegalAccessException : 類定義不明確所產(chǎn)生的異常。
· InstantiationException : 使用 newInstance( )方法試圖建立一個類 instance時所產(chǎn)生的異常。
· InterruptedException : 目前線程等待執(zhí)行,另一線程中斷目前線程所產(chǎn)生的異常。
Error 類與異常一樣,它們都是繼承自 java.lang.Throwable 類。 Error 類對象由 Java 虛擬機生成并拋出。 Error 類包括 LinkageError (結(jié)合錯誤)與 VitualmanchineError (虛擬機錯誤)兩種子類。
LinkageError 類的子類表示一個類信賴于另一個類,但是,在前一個類編譯之后,后一個類的改變會與它不兼容。
LinkageError 類包括 ClassFormatError 、 ClassCircularityError 、 ExceptionInitializerError 、 NoClassDeFormatError 、 VeritfyError 、 UnsatisfidLinkError 和 IncompatibleClassChangeError 等子類。其中 NoIncompatibleClassChangeError 類又包含 AbstractMethodError 、 NoSuchField Error 、 NoSuchMethodError 、 IllegalAccessError 和 InstantiationError 子類。這些類所代表的意義如下所述。
· ClassFormatError : 類格式所產(chǎn)生的錯誤。
· ClassCircularityError : 無限循環(huán)所產(chǎn)生的錯誤。
· ExceptionInitializerError : 初始化所產(chǎn)生的錯誤。
· NoClassDeFormatError : 沒有類定義所產(chǎn)生的錯誤。
· VeritfyError : 類文件某些數(shù)據(jù)不一致或安全問題所產(chǎn)生的錯誤。
· UnsatisfidLinkError : Java虛擬機無法找到合適的原始語言( Native-Language)定義的方法所產(chǎn)生的錯誤。
· IncompatibleClassChangeError : 不兼容類所產(chǎn)生的錯誤。
· AbtractMethodError : 調(diào)用抽象方法所產(chǎn)生的錯誤。
· NoSuchFieldError : 存取或改變數(shù)據(jù)域所產(chǎn)生的錯誤。
· NoSuchMethodError : 調(diào)用類方法所產(chǎn)生的錯誤。
· IllegalAccessError : 不合法存取或改變數(shù)據(jù)域調(diào)用方法所產(chǎn)生的錯誤。
· InstantiationError : 使用抽象類或接口所產(chǎn)生的錯誤。
當 Java 虛擬機崩潰了或用盡了它繼續(xù)操作所需的資源時,拋出該錯誤。
VitualmachineError 包含 InternalError 、 OutOfMemoryError 、 StackOverflow Error 和 UnknownError 。這些類所代表的意義如下所述。
· InternalError : 虛擬機內(nèi)部所產(chǎn)生的錯誤。
· OutOfMemoryError : 虛擬機內(nèi)存不足所產(chǎn)生的錯誤。
· StackOverflowError : 堆棧無法容納所產(chǎn)生的錯誤。
· UnknownError : 虛擬機不知名異常所產(chǎn)生的錯誤。
Java 提供了一種獨特的異常處理機制,通常通過異常來處理程序設(shè)計中可能出現(xiàn)的錯誤 。
在 Java 程序的執(zhí)行過程中,如果出現(xiàn)了異常事件,就會生成一個異常對象;生成的異常對象將傳遞給 Java 運行系統(tǒng),這一異常的產(chǎn)生和提交過程稱為拋棄( Throw )異常。當 Java 運行系統(tǒng)得到一個異常對象時,它將會尋找處理這一異常的代碼,找到能夠處理這種類型異常的方法后,運行系統(tǒng)把當前異常對象交給這個方法進行處理,這一過程稱為捕獲( Catch )異常。如果 Java 運行系統(tǒng)找不到可以捕獲異常的方法,則運行系統(tǒng)將終止,相應(yīng)的 Java 程序也將退出。
Java 異常處理是通過 5 個關(guān)鍵字來管理的。它們是 try 、 catch 、 throw 、 throws 和 finally, 將在下面的小節(jié)中詳細介紹。這里先大致給出它們的工作原理。
程序中需要被監(jiān)測的程序語句序列應(yīng)包含在一個 try 代碼塊中。如果 try 代碼塊中有異常發(fā)生,那么就要拋出該異常??梢杂?/span> catch 代碼塊來捕獲這個異常,并且在 catch 代碼塊中加以適當?shù)奶幚?。系統(tǒng)產(chǎn)生的異常會由 Java 運行系統(tǒng)自動拋出。如果需要手動拋出異常,則使用關(guān)鍵字 throw 。在某些情況下,從一個方法拋出的異常必須用一個 throw 語句指定為異常。最后,從 try 代碼塊退出時,必須執(zhí)行的代碼要放在一個 finallly 代碼塊中。
異常機制提供了程序退出的安全通道。當出現(xiàn)錯誤后,程序執(zhí)行的流程發(fā)生改變,程序的控制權(quán)轉(zhuǎn)移到異常處理器。傳統(tǒng)的處理異常的辦法是:方法返回一個特殊的結(jié)果來表示出現(xiàn)異常,調(diào)用該方法的程序負責檢查并分析函數(shù)返回的結(jié)果并進行相應(yīng)的處理。但是,這樣做有如下弊端:
· 函數(shù)返回 - 1代表出現(xiàn)異常,但是如果函數(shù)確實要返回 - 1這個正確的值時,就會出現(xiàn)混淆。
· 可讀性降低,將程序代碼與處理異常的代碼交叉在一起。
· 由調(diào)用函數(shù)的程序來分析錯誤,這就要求客戶程序員對庫函數(shù)有很深的了解。
J ava 的異??梢苑譃檫\行時異常和非運行時異常兩類。繼承于 RuntimeException 的類都屬于運行時異常,例如算術(shù)異常、數(shù)組下標越界異常等。由于這些異常產(chǎn)生的位置是未知的, Java 編譯器允許程序員在程序中不對它們做出處理。除了運行時異常之外的其他由 Exception 繼承來的異常都是非運行時異常, Java 編譯器要求在程序中必須處理這種異常 。
異常處理的目的并不是為了避免發(fā)生異常,而是在異常發(fā)生時避免程序的異常終止,設(shè)法將損失降低到最小。
Java 的異常處理是通過 5 個關(guān)鍵詞來實現(xiàn)的: try 、 catch 、 throw 、 throws 和 finally 。一般情況下是用 try 來執(zhí)行一段程序,如果出現(xiàn)異常,系統(tǒng)會拋出( throw )一個異常,這時候可以通過它的類型來捕捉( catch )它,最后( finally )由默認處理器來處理。
在 Java 程序里,異常對象是依靠 try/catch 語句來捕獲和處理的。 try/catch 異常處理語句分為 try 語句塊和 catch 語句塊,其格式如下。
try{
…… //try語句塊,可能產(chǎn)生異常的多個語句
}catch{
…… //catch語句塊,對異常進行處理
}
一般將可能產(chǎn)生異常情況語句放在 try 語句塊中,這個 try 語句塊用來啟動 Java 的異常處理機制。凡是可能拋出異常的語句,包括 throw 語句和可能拋出異常的方法的調(diào)用語句,都應(yīng)該包含在這個 try 語句塊中。然后在 catch 語句塊對異常進行處理。 Java 語言還規(guī)定,每個 catch 語句塊都應(yīng)該與一個 try 語句塊相對應(yīng)。
【例 8-1 】 捕獲除數(shù)為零的異常,并顯示相應(yīng)信息。
class ArithmeticExceptionDemo{
public static void main(String args[]) {
int zero,aInt;
try {// 監(jiān)視可能產(chǎn)生異常的代碼塊
zero=0;
aInt=68/zero;
System.out.println("本字符串將不顯示。 ");
}catch (ArithmeticException e) { //捕獲 divide-by-zero錯誤
System.out.println("產(chǎn)生用零除錯誤。 ");
}
System.out.println("在捕獲語句后執(zhí)行的一個語句。 ");
}
}
該程序的執(zhí)行結(jié)果如圖 8-2 所示。
圖 8-2 捕獲 divide-by-zero錯誤的執(zhí)行結(jié)果
Try 語句塊中調(diào)用了可能拋出 ArithmeticException 的對象, catch 語句塊則專門用來捕獲這類異常??梢姡?/span> catch 語句塊應(yīng)緊跟在 try 語句塊的后面。當 try 語句塊中的某條語句在執(zhí)行時產(chǎn)生了一個異常,此時被啟動的異常處理機制會自動捕獲到它,然后流程自動跳過異常引發(fā)點后面的所有尚未執(zhí)行語句,而轉(zhuǎn)至 try 語句塊后面的 catch 語句塊,執(zhí)行 catch 語句塊中的語句。從執(zhí)行的結(jié)果還可以看出,異常被捕獲并執(zhí)行完 catch 語句塊中的語句后,繼續(xù)執(zhí)行 catch 語句塊之后的語句。如果沒有異常發(fā)生,則跳過 catch 語句塊。
finally 語句塊用來控制從 try-catch 語句轉(zhuǎn)移到另一部分之前的一些必要的善后工作,這些工作包括關(guān)閉文件或釋放其他有關(guān)系統(tǒng)資源等。 finally 語句塊中的語句是一種強制的、無條件執(zhí)行的語句,即無論在程序中是否出現(xiàn)異常,無論出現(xiàn)哪一種異常,也不管 try 代碼塊中是否包含有 break 、 continue 、 return 或者 throw 語句,都必須執(zhí)行 finally 語句塊中所包含的語句。
finally 語句塊緊接著 try-catch 結(jié)構(gòu)中的最后一個 catch 語句塊,其形式如下:
try{
……
}catch(Exception1 e1){
……
}catch(Exception2 e2){
……
} finally{
……
}
在出現(xiàn)和未出現(xiàn)異常的情況下都要執(zhí)行的代碼可以放到 finally 語句塊中。加入了 finally 語句塊后有以下 3 種執(zhí)行情況。
· 沒有拋出異常情況: 執(zhí)行 try語句塊后,再執(zhí)行 finally語句塊。
· 代碼拋出在 catch 語句塊中捕獲的一個異常情況: 這時, Java執(zhí)行 try語句塊中直到這個異常情況被拋出為止的所有代碼,跳過 try語句塊中剩余的代碼;然后執(zhí)行匹配的 catch語句塊中的代碼和 finally語句塊中的代碼。
· 代碼拋出了一個在 catch 語句塊中沒有捕獲到的異常情況: 這時, Java執(zhí)行 try語句塊中直到這個異常情況被拋出為止的所有代碼,跳過 try語句塊中剩余的代碼;然后執(zhí)行 finally語句塊中的代碼,并把這個異常情況拋回到這個方法的調(diào)用者。
【例 8-2 】 帶有 finally 語句塊的程序示例。
class Finally_Demo{
public static void main(String args[]) {
try{
int x=0;
int y=20;
int z=y/x;
System.out.println("y/x 的值是 :"+z);
}catch(ArithmeticException e){
System.out.println(" 捕獲到算術(shù)異常 : "+e);
}finally{
System.out.println(" 執(zhí)行到 finally 塊內(nèi) ! ");
try{
String name=null;
if(name.equals(" 王老三 ")){
// 字符串比較 , 判斷 name 是否為 " 王老三 "
System.out.println(" 你 的名字叫王老三。 ");
}
}catch(Exception e){
System.out.println(" 又捕獲到另一個異常 : "+e);
}finally{
System.out.println(" 執(zhí)行到內(nèi)層的 finally 塊內(nèi) ! ");
}
}
}
}
該程序的執(zhí)行結(jié)果如圖 8-3 所示。
圖 8-3 帶有 finally語句塊的程序的執(zhí)行結(jié)果
在 Java 語言中, try-catch-finally 語句允許嵌套。本例就是將內(nèi)層的一個 try 嵌套在外層的 finally 語句塊內(nèi)。在程序執(zhí)行到外層的 try 語句塊時,由于分母為零而產(chǎn)生了算術(shù)異常,所以程序轉(zhuǎn)移到第一個 catch 語句塊。該 catch 語句塊捕獲了這個算術(shù)異常,并進行了處理,之后再轉(zhuǎn)向必須執(zhí)行的外層的 finally 語句塊。因為在該 finally 語句塊內(nèi)又產(chǎn)生了空指針異常(一個 null 字符串和字符串"王老三"進行比較),所以內(nèi)層 catch 語句塊又捕獲到 NullPointerException ,最后程序轉(zhuǎn)移到內(nèi)層的 finally 語句塊。
finally 語句塊還可以和 break 、 continue 以及 return 等流程控制語句一起使用。當 try 語句塊中出現(xiàn)了上述語句時,程序必須先執(zhí)行 finally 語句塊,才能最終離開 try 語句塊。
【例 8-3 】 同時有 break 語句和 finally 語句塊的程序的執(zhí)行情況。
class FinallyWithBreakDemo{
public static void main(String args[]) {
for( ; ; )
try{
System.out.println("即將被 break中斷,要退出循環(huán)了 !");
break;
}finally{
System.out.println("但是 finally塊總要被執(zhí)行到! ");
}
}
}
該程序的執(zhí)行結(jié)果如圖 8-4 所示。
圖 8-4 同時有 finally語句塊和 break語句的程序的執(zhí)行結(jié)果
在某些情況下,如果一個方法產(chǎn)生自己不處理或無法處理的異常,它就必須在 throws 子句中聲明該異常。也就是說,在 Java 語言中如果在一個方法中生成了一個異常,但是這一方法并不確切地知道該如何對這一異常事件進行處理,這時,這個方法就應(yīng)該聲明拋棄異常,使得異常對象可以從調(diào)用棧向后傳播,直到有適合的方法捕獲它為止。
throws 關(guān)鍵字是在方法聲明中用來列出從方法中發(fā)出的非起源于 Error 或 RutimeException 中的任何異常。能夠主動引發(fā)異常的方法必須用 throws 來聲明。通常使用 Java 預(yù)定義的異常類就可以滿足程序開發(fā)者的編程需要。
聲明拋棄異常是在一個方法中的 throws 子句中指明的。
下面是包含 throws 子句的方法的基本形式。
[修飾符 ] 返回類型 方法名(參數(shù) 1,參數(shù) 2,……) throws異常列表
{…… }
例如:
public int read ( ) throws IOException
{…… }
throws 子句中同時可以指明多個異常,說明該方法將不對這些異常進行處理,而是聲明拋棄它們。例如:
public static void main (String args[ ]) throws IOException, IndexOutOf-
BoudsException
{…… }
【例 8-4 】 聲明拋出異常的程序格式。
import java.io.*;
public class ExceptionExam5
{
public static void go() throws IOException
{//方法代碼 }
public static void main(String [] args)
{//程序入口主方法代碼 }
}
因為考慮到 go() 方法可能產(chǎn)生一個 IOException ,而此時無法處理異常,所以要從 go() 方法拋出這個異常,并且需要用 throws 子句指定異常。另外, Java 的 I/O 系統(tǒng)包含在 java.io 包中,因此 IOException 也包含在其中,所以使用語句“ import java.io.*; ”導(dǎo)入 java.io 包,然后可以直接引用 IOException 。
Java 應(yīng)用程序在運行時如果出現(xiàn)了一個可識別的錯誤,就會產(chǎn)生一個與該錯誤相對應(yīng)的異常類的對象。這個對象包含了異常的類型和錯誤出現(xiàn)時程序所處的狀態(tài)信息,該異常對象首先被交給 Java 虛擬機,由虛擬機來尋找具體的異常處理者。在 Java 中把產(chǎn)生異常對象并將其交給 Java 虛擬機的過程稱為拋出異常。
異常類不同,拋出異常的方法也不同,可以分為以下兩種。
· 系統(tǒng)自動拋出的異常。
· 語句拋出的異常。
系統(tǒng)定義的所有運行異常都可以由系統(tǒng)自動拋出。例如,以非法的算術(shù)操作引發(fā)的算術(shù)異常,這時系統(tǒng)拋出已定義好的異常類 ArithmeticException 的對象。前面列出的例子中,基本都屬于系統(tǒng)自動拋出的異常。
語句拋出的異常是借助 throw 語句定義何種情況產(chǎn)生這種異常。用戶程序自定義的異常不可能依靠系統(tǒng)自動拋出,必須使用 throw 語句拋出這個異常類的新對象。系統(tǒng)定義的運行異常也可以由 throw 語句拋出。用 throw 語句拋出異常對象的一般步驟如下:
( 1 )指定或定義一個合適的異常情況類。
( 2 )產(chǎn)生這個類的一個對象。
( 3 )拋出它。
例如:
EOFException e = new EOFException( );
throw e;
使用 throw 語句拋出異常有兩種方式:直接拋出和間接拋出。
直接拋出方式是直接利用 throw 語句將異常拋出,格式為:
throw newExceptionObject;
利用 throw 語句拋出一個異常后,程序執(zhí)行流程將直接尋找一個捕獲( catch )語句,并進行匹配執(zhí)行相應(yīng)的異常處理程序,其后的所有語句都將被忽略。
【例 8-5 】 設(shè)計自己的異常類,從鍵盤輸入一個 double 類型的數(shù),若不小于 0.0 ,則輸出它的平方根;若小于 0.0 ,則輸出提示信息“輸入錯誤”。
import java.io.*;
class MyException extends Exception{
void test(double x) throws MyException{
if(x<0.0) throw new MyException(); //條件成立時,執(zhí)行 throw語句
else System.out.println(Math.sqrt(x));
}
public static void main(String args[]) throws IOException{
MyException n = new MyException();
try{
System.out.print("求輸入實數(shù)的平方根。請輸入一個實數(shù): ");
BufferedReader br=
new BufferedReader(new InputStreamReader(System.in) );
String s=br.readLine();
n.test(Double.parseDouble(s));
}catch(MyException e){
System.out.println("輸入錯誤! ");
}
}
}
程序的兩次運行結(jié)果如圖 8-5 所示。
圖 8-5 MyException類的兩次運行結(jié)果
在這個程序中,定義的異常類通過 extends 子句繼承了 Exception 異常類。在 test( ) 方法中,用 throw 語句指定了可能拋出的異常,該語句在參數(shù)小于 0 時被執(zhí)行,產(chǎn)生并拋出異常 。
值得注意的是:在一個方法定義中如果采用了 throw 語句直接拋出異常,則該方法在發(fā)生異常的情況下可能沒有返回值。本例就屬于這種情況。
從本例也可以看出:由于系統(tǒng)不能識別用戶自定義的異常,所以需要編程人員在程序中的合適位置創(chuàng)建自定義異常的對象,并利用 throw 語句將這個新異常對象拋出。
在 Java 程序中,可以在方法的定義中利用 throws 關(guān)鍵字聲明異常類型而間接拋出異常。也就是說,當 Java 程序中方法本身對其中出現(xiàn)的異常并不關(guān)心或不方便處理時,可以不在方法實現(xiàn)中直接捕獲有關(guān)異常并進行處理,而是在方法定義的時候通過 throws 關(guān)鍵字,將異常拋給上層調(diào)用處理。其形式如下。
public void myMethod1() throws IndexOutOfBoundsException {
……
}
或
public void myMethod2() throws myException1, myException2 {
……
}
在上層調(diào)用該方法時,必須捕獲有關(guān)異常,否則編譯時將會出錯。例如,調(diào)用方法 myMethod2() 時,必須按如下方式進行。
try{
myMethod2
}catch (MyExceptionl e1){
……
}catch(MyException2 e2){
……
}
【例 8-6 】 帶有間接拋出異常的類。
public class OutOfRangeException extends Exception{
public OutOfRangeException(){};
public OutOfRangeException(Sting s){
super(s);
}
} // 定義一個異常類
import OutOfRangeException; //裝載異常類
import java.io.*;
public class CreatingExceptions{
private static BufferedReader in = new BufferedReader
(new InputStreamReader(System.in));
public static void main (String[] args) throws OutOfRangeException{
final int MIN = 25, MAX = 40;
int value;
OutOfRangeException problem =
new OutOfRangeException ("Input value is out of range.");
//創(chuàng)建一個異常對象并可能拋出它
System.out.print ("Enter an integer value between " + MIN +
" and " + MAX + ", inclusive: ");
try{
value = Integer.parseInt (in.readLine());
}catch (Exception exception) {
System.out.println ("Error reading int data, MIN_VALUE value
returned.");
value = Integer.MIN_VALUE;
}
//確定該異常是否拋出
if (value < MIN || value > MAX)
throw problem;
System.out.println ("End of main method.");
//may never reach this place
}
}
這個例子有兩個特征,一是它利用了自定義的異常類 OutOfRangeException ,一旦程序執(zhí)行違背了所定義的邏輯就拋出這個異常;二是在拋出異常的方法中,利用 throws 關(guān)鍵字聲明了 OutOfRangeException 異常類的間接拋出,這樣若是在其他地方使用到這個類的對象,也可以捕獲這個異常。
使用 throws 子句拋出異常時應(yīng)注意如下兩個問題。
· 一般這種拋出異常的語句應(yīng)該被定義為在滿足一定條件時執(zhí)行,例如把 throws子句放在 if語句的條件分支中,只有當條件得到滿足,即用戶定義的邏輯錯誤發(fā)生時才拋出。例如,例 8-6中的條件( value < MIN || value > MAX)滿足時,拋出異常。
· 對于含有 throws子句的方法,應(yīng)該在方法頭定義中增加如下部分。
throws異常類名列表
這樣做主要是為了通知所有欲調(diào)用此方法的方法:由于該方法包含 throws了句,所以要準備接受和處理它在運行過程中可能會拋出的異常。如果方法中的 throws了句不止一個,方法頭的異常類名表中的列出的異常也不止一個,應(yīng)該包含所有可能產(chǎn)生的異常。例如,在上面的 myMethod2( ) 方法中包含的異常有: myException1 和 myException2 。
注意: 執(zhí)行 throws子語句將中斷程序的執(zhí)行,也就是說 throws的下一條語句將暫停執(zhí)行。
在實際的編程中并不一定非要使用 Java 已經(jīng)定義的異常,經(jīng)常需要創(chuàng)建自己的異常,以便指出編寫的代碼可能生成的一個特殊錯誤。創(chuàng)建自己的異常類,必須從一個現(xiàn)有的異常類型(最終繼承自 Throwable 類)繼承。繼承一個異常同繼承一個普通的類的方法是一樣的 。
Java 提供的一些異常有時候不能滿足編程的需求,例如規(guī)定用戶輸入數(shù)據(jù)的范圍在 20 到 30 之間,但是 Java 并沒有這個方面的異常,這時就可以應(yīng)用自定義的異常來規(guī)范化客戶的數(shù)據(jù)輸入。
在 Java 中進行自定義異常時,自定義異常類必須是 Throwable 類的直接或間接子類。下面的例子是關(guān)于自定義異常的。它通過繼承 Exception 類而繼承 Throwable 類,即間接繼承 Throwable 類。
【例 8-7 】 自定義異常類程序示例。
class OutBoundsException extends Exception
{
OutBoundsException (String mes)
{
// 調(diào)用超類的構(gòu)造函數(shù)
super(mes);
}
}
class check
{
String ChecktheNum(int n) throws OutBoundsException
{
Integer N=new Integer(n);
if(n>30||n<20)
throw new OutBoundsException("the number is out of bound!!");
else
return "the number"+N.toString()+"is in the bound!!";
}
}
class Test
{
public static void main(String []args)
{
try
{
check c=new check();
System.out.println(" 以下是合法的數(shù)據(jù)的報告! ");
System.out.println(c.ChecktheNum(25));
System.out.println(" 以下是非法的數(shù)據(jù)的報告! ");
System.out.println(c.ChecktheNum(5));
}
catch(OutBoundsException e)
{
System.out.println(e.toString());
}
}
}
運行結(jié)果如圖 8-6 所示。
圖 8-6 運行結(jié)果
注意: 一個方法所聲明拋棄的異常是作為這個方法與外界交互的一部分而存在的。 所以,方法的調(diào)用者必須了解這些異常,并確定如何正確地處理它們。
<script></script>