Java 中的例外處理除了包括捕獲異常和處理異常之外,還包括宣告異常和拋出異常,
可以通過 throws 關鍵字在方法上宣告該方法要拋出的異常,然後
在方法內部通過 throw 拋出異常物件。本節詳細介紹在 Java 中如何宣告異常和拋出異常。
throws 關鍵字和 throw 關鍵字在使用上的幾點區別如下:
-
throws 用來宣告一個方法可能丟擲的所有異常資訊,throw 則是指拋出的一個具體的異常型別。
-
通常在一個方法(類)的宣告處通過 throws 宣告方法(類)可能拋出的異常資訊,而在方法(類)內部通過 throw 宣告一個具體的異常資訊。
-
throws 通常不用顯示地捕獲異常,可由系統自動將所有捕獲的異常資訊拋給上級方法; throw 則需要使用者自己捕獲相關的異常,而後再對其進行相關包裝,最後將包裝後的異常資訊丟擲。
throws 宣告異常
當一個方法產生一個它不處理的異常時,那麼就需要在該方法的頭部宣告這個異常,以便將該異常傳遞到方法的外部進行處理。可以使用 throws 關鍵字在方法的頭部宣告一個異常,其具體格式如下:
returnType method_name(paramList) throws Exception 1,Exception2,…{…}
其中,returnType 表示返回值型別,method_name 表示方法名,Exception 1,Exception2,… 表示異常類。
如果有多個異常類,它們之間用逗號分隔。這些異常類可以是方法中呼叫了可能拋出異常的方法而產生的異常,也可以是方法體中生成並拋出的異常。
例 1
建立一個 readFile() 方法,該方法用於讀取檔案內容,在讀取的過程中可能會產生 IOException 異常,但是在該方法中不做任何的處理,而將可能發生的異常交給呼叫者處理。在 main() 方法中使用 try catch 捕獲異常,並輸出異常資訊。程式碼如下:
import java.io.FileInputStream;
import java.io.IOException;
public class Test04 {
public void readFile() throws IOException {
// 定義方法時宣告異常
FileInputStream file = new FileInputStream("read.txt"); // 建立 FileInputStream 範例物件
int f;
while ((f = file.read()) != -1) {
System.out.println((char) f);
f = file.read();
}
file.close();
}
public static void main(String[] args) {
Throws t = new Test04();
try {
t.readFile(); // 呼叫 readFHe()方法
} catch (IOException e) {
// 捕獲異常
System.out.println(e);
}
}
}
以上程式碼,首先在定義 readFile() 方法時用 throws 關鍵字宣告在該方法中可能產生的異常,然後在 main() 方法中呼叫 readFile() 方法,並使用 catch 語句捕獲產生的異常。
注意:
在編寫類繼承程式碼時要注意,子類在覆蓋父類別帶 throws 子句的方法時,子類的方法宣告中的 throws 子句不能出現父類別對應方法的 throws 子句中沒有的異常型別,因此 throws 子句可以限制子類的行為。也就是說,子類方法拋出的異常不會超過父類別定義的範圍。
throw 拋出異常
throw 語句用來直接拋出一個異常,後接一個可拋出的異常類物件,其語法格式如下:
throw ExceptionObject;
其中,ExceptionObject 必須是 Throwable 類或其子類的物件。如果是自定義異常類,也必須是 Throwable 的直接或間接子類。例如,以下語句在編譯時將會產生語法錯誤:
throw new String("拋出異常"); // 因為String類不是Throwable類的子類
當 throw 語句執行時,它後面的語句將不執行,此時程式轉向呼叫者程式,尋找與之相匹配的 catch 語句,執行相應的例外處理程式。如果沒有找到相匹配的 catch 語句,則再轉向上一層的呼叫程式。這樣逐層向上,直到最外層的例外處理程式終止程式並列印出呼叫棧情況。
例 2
在某倉庫管理系統中,要求管理員的使用者名稱需要由 8 位以上的字母或者數位組成,不能含有其他的字元。當長度在 8 位以下時拋出異常,並顯示異常資訊;當字元含有非字母或者數位時,同樣拋出異常,顯示異常資訊。程式碼如下:
import java.util.Scanner;
public class Test05 {
public boolean validateUserName(String username) {
boolean con = false;
if (username.length() > 8) {
// 判斷使用者名稱長度是否大於8位元
for (int i = 0; i < username.length(); i++) {
char ch = username.charAt(i); // 獲取每一位字元
if ((ch >= '0' && ch <= '9') || (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) {
con = true;
} else {
con = false;
throw new IllegalArgumentException("使用者名稱只能由字母和數位組成!");
}
}
} else {
throw new IllegalArgumentException("使用者名稱長度必須大於 8 位!");
}
return con;
}
public static void main(String[] args) {
Test05 te = new Test05();
Scanner input = new Scanner(System.in);
System.out.println("請輸入使用者名稱:");
String username = input.next();
try {
boolean con = te.validateUserName(username);
if (con) {
System.out.println("使用者名稱輸入正確!");
}
} catch (IllegalArgumentException e) {
System.out.println(e);
}
}
}
如上述程式碼,在 validateUserName() 方法中兩處拋出了 IllegalArgumentException 異常,即當使用者名稱字元含有非字母或者數位以及長度不夠 8 位時。在 main() 方法中,呼叫了 validateUserName() 方法,並使用 catch 語句捕獲該方法可能拋出的異常。
執行程式,當使用者輸入的使用者名稱包含非字母或者數位的字元時,程式輸出異常資訊,如下所示。
請輸入使用者名稱:
[email protected]#
java.lang.IllegalArgumentException: 使用者名稱只能由字母和數位組成!
當使用者輸入的使用者名稱長度不夠 8 位時,程式同樣會輸出異常資訊,如下所示。
請輸入使用者名稱:
admin
java.lang.IllegalArgumentException: 使用者名稱長度必須大於 8 位!