丟擲異常
以下示例顯示了丟擲異常的基礎知識:
public void checkNumber(int number) throws IllegalArgumentException {
if (number < 0) {
throw new IllegalArgumentException("Number must be positive: " + number);
}
}
在第 3 行丟擲異常。本宣告可分為兩部分:
-
new IllegalArgumentException(...)
正在建立IllegalArgumentException
類的例項,並帶有描述異常報告錯誤的訊息。 -
然後
throw ...
丟擲異常物件。
丟擲異常時,會導致封閉語句異常終止,直到處理**異常為止。這在其他示例中描述。
最好在單個語句中建立和丟擲異常物件,如上所示。在異常中包含有意義的錯誤訊息也是一種很好的做法,可以幫助程式設計師理解問題的原因。但是,這不一定是你應向終端使用者顯示的訊息。 (首先,Java 沒有直接支援國際化異常訊息。)
還有幾點要做:
-
我們宣稱
checkNumber
為throws IllegalArgumentException
。這不是絕對必要的,因為IllegalArgumentException
是一個經過檢查的例外; 請參閱 Java 異常層次結構 - 未選中和已檢查的異常 。但是,最好這樣做,並且還要包含丟擲方法的 javadoc 註釋的異常。 -
無法訪問
throw
語句後的程式碼。因此,如果我們寫這個:throw new IllegalArgumentException("it is bad"); return;
編譯器將報告
return
語句的編譯錯誤。
連結異常
除了傳統的 message
引數之外,許多標準異常都有一個帶有第二個 cause
引數的建構函式。cause
允許你連結異常。這是一個例子。
首先,我們定義一個未經檢查的異常,當我們的應用程式遇到不可恢復的錯誤時,它會丟擲。請注意,我們已經包含了一個接受 cause
引數的建構函式。
public class AppErrorException extends RuntimeException {
public AppErrorException() {
super();
}
public AppErrorException(String message) {
super(message);
}
public AppErrorException(String message, Throwable cause) {
super(message, cause);
}
}
接下來,這是一些說明異常連結的程式碼。
public String readFirstLine(String file) throws AppErrorException {
try (Reader r = new BufferedReader(new FileReader(file))) {
String line = r.readLine();
if (line != null) {
return line;
} else {
throw new AppErrorException("File is empty: " + file);
}
} catch (IOException ex) {
throw new AppErrorException("Cannot read file: " + file, ex);
}
}
try
塊中的 throw
檢測到問題並通過簡單訊息通過異常報告。相比之下,catch
塊中的 throw
通過將其包裝在新的(已檢查)異常中來處理 IOException
。但是,它並沒有丟掉原來的例外。通過將 IOException
作為 cause
傳遞,我們將其記錄下來,以便可以在堆疊跟蹤中列印,如建立和讀取堆疊跟蹤中所述。