你好!在上一講中,我們熟悉了 Java 語言的異常方面,並看到了使用它們的範例。今天我們將更深入地了解它們的結構,並學習如何編寫我們自己的異常:)
例外的類型
正如我們所說,Java中有很多異常類,幾乎有400個!但它們都分為不同的組,所以很容易記住它們。它看起來像這樣: 所有異常都有一個共同的祖先類別Throwable
。兩大類來自於它-異常(Exception)和錯誤(Error)。錯誤是與Java虛擬機器操作相關的程式執行期間的嚴重錯誤。在大多數情況下,錯誤不需要處理,因為它表明程式碼中存在一些嚴重缺陷。最著名的錯誤:StackOverflowError
- 例如,當一個方法無休止地調用自身時發生;以及OutOfMemoryError
- 當沒有足夠的內存來創建新對象時發生。正如您所看到的,在這些情況下,大多數情況下沒有什麼特別需要處理的 - 程式碼只是寫得不正確,需要重做。 異常其實就是異常:程式運作時發生的異常的、計畫外的情況。這些錯誤不像Error那麼嚴重,但需要我們注意。所有異常分為2種類型-已檢查(checked)和未檢查(unchecked)。 所有已檢查的異常都來自Exception
. 「可驗證」是什麼意思?我們在上一講中部分提到了這一點: “...Java 編譯器知道最常見的異常,並且知道它們在什麼情況下會發生。” 例如,他知道如果程式設計師用程式碼從檔案中讀取數據,很容易出現該檔案不存在的情況。而且這樣的情況還有很多,他是可以提前預測的。因此,編譯器會提前檢查我們的程式碼是否有潛在的異常。如果它找到它們,它不會編譯程式碼,直到我們處理它們或將它們轉發到頂部。第二種異常是「未經檢查的」。他們來自班級RuntimeException
。它們與正在測試的有什麼不同?似乎還有一堆不同的類別來自RuntimeException
並描述特定的運行時異常。不同之處在於編譯器不會預料到這些錯誤。他似乎在說:「在編寫程式碼時,我沒有發現任何可疑之處,但在運行時出了問題。顯然程式碼中有錯誤!” 確實如此。未經檢查的異常通常是程式設計師錯誤的結果。 並且編譯器顯然無法提供人們可以親手創建的所有可能的錯誤情況:)因此,它不會檢查我們程式碼中此類異常的處理。您已經遇到過幾個未經檢查的異常:
ArithmeticException
除以零時發生ArrayIndexOutOfBoundsException
嘗試存取數組外部的單元格時發生。
如何拋出例外
當然,Java 的創建者無法應對程式中可能出現的所有異常情況。世界上的程式太多,差異太大。但這沒關係,因為如果需要,您可以創建自己的異常。這很容易完成。您所要做的就是創建自己的類別。其名稱必須以“Exception”結尾。編譯器不需要這個,但是閱讀程式碼的程式設計師會立刻明白這是一個異常類別。另外,需要顯示該類別來自於該類別Exception
。這對於編譯器和正確操作來說已經是必要的。例如,我們有一個 Dog 類別Dog
。我們可以使用 遛狗walk()
。但在此之前,我們需要檢查我們的寵物是否戴著項圈、皮帶和口套。如果缺少其中任何一個,我們將拋出我們自己的異常DogIsNotReadyException
。它的程式碼如下所示:
public class DogIsNotReadyException extends Exception {
public DogIsNotReadyException(String message) {
super(message);
}
}
為了表示一個類別是異常,你需要在類別名稱後面寫extends Exception :這表示「該類別是從Exception類別衍生而來。在建構函式中,我們將簡單地用一行呼叫類別建構函式Exception
-message
它將向使用者顯示一條來自系統的訊息,描述已發生的錯誤。這就是我們的類別代碼中的樣子:
public class Dog {
String name;
boolean isCollarPutOn;
boolean isLeashPutOn;
boolean isMuzzlePutOn;
public Dog(String name) {
this.name = name;
}
public static void main(String[] args) {
}
public void putCollar() {
System.out.println("The collar is on!");
this.isCollarPutOn = true;
}
public void putLeash() {
System.out.println("The leash is on!");
this.isLeashPutOn = true;
}
public void putMuzzle() {
System.out.println("The muzzle is on!");
this.isMuzzlePutOn = true;
}
public void walk() throws DogIsNotReadyException {
System.out.println("Let's go for a walk!");
if (isCollarPutOn && isLeashPutOn && isMuzzlePutOn) {
System.out.println("Hurrah, let's go for a walk!" + name + " I am glad!");
} else {
throw new DogIsNotReadyException("Dog " + name + "not ready for a walk! Check your gear!");
}
}
}
現在我們的方法walk()
拋出異常DogIsNotReadyException
。這是使用關鍵字 完成的throw
。正如我們之前所說,異常是一個物件。因此,在我們的方法中,當發生異常情況時(狗身上缺少某些東西),我們創建一個新的類別物件並使用單字DogIsNotReadyException
將其放入程式中throw
。walk()
我們將 throws 加入方法簽章DogIsNotReadyException
。換句話說,編譯器現在知道方法呼叫walk()
可能會導致異常。因此,當我們在程式中的某個地方呼叫它時,就需要處理異常。讓我們嘗試在方法中執行此操作main()
:
public static void main(String[] args) {
Dog dog = new Dog("Mukhtar");
dog.putCollar();
dog.putMuzzle();
dog.walk();//Unhandled exception: DogIsNotReadyException
}
無法編譯,異常未處理!讓我們將程式碼包裝在一個區塊中try-catch
來處理異常:
public static void main(String[] args) {
Dog dog = new Dog("Mukhtar");
dog.putCollar();
dog.putMuzzle();
try {
dog.walk();
} catch (DogIsNotReadyException e) {
System.out.println(e.getMessage());
System.out.println("Checking equipment! Is the collar on?" + dog.isCollarPutOn + "\r\n Is the leash on?"
+ dog.isLeashPutOn + "\r\n Are you wearing a muzzle?" + dog.isMuzzlePutOn);
}
}
現在讓我們來看看控制台輸出:
Ошейник надет!
Намордник надет!
Собираемся на прогулку!
Собака Мухтар не готова к прогулке! Проверьте экипировку!
Проверяем снаряжение! Ошейник надет? true
Поводок надет? false
Намордник надет? true
看看控制台輸出的資訊變得多麼豐富!我們可以看到程序中發生的每一步;我們看到錯誤發生的位置並立即註意到我們的狗到底缺少什麼:)這就是我們創建自己的異常的方式。如您所見,沒什麼複雜的。儘管 Java 開發人員並沒有費心在他們的語言中為裝備不正確的狗添加一個特殊的例外,但我們糾正了他們的疏忽:)
GO TO FULL VERSION