CodeGym /Java Blog /Toto sisi /異常:選中、未選中和自定義
John Squirrels
等級 41
San Francisco

異常:選中、未選中和自定義

在 Toto sisi 群組發布
你好!在上一課中,我們熟悉了 Java 語言中的異常,並看到瞭如何使用它們的示例。今天我們將深入了解異常的結構,並學習如何編寫我們自己的異常 :)

異常類型

正如我們之前所說,Java 中的異常非常多,幾乎有 400 個!但它們都被分成幾組,所以很容易記住它們。它看起來是這樣的: 例外:選中、未選中和自定義 - 2 所有異常在Throwable類中都有一個共同的祖先。從中派生出兩大類:異常(Exception)和錯誤(Error)。 錯誤- 這表示與 Java 虛擬機操作相關的嚴重運行時錯誤。在大多數情況下,Error 不需要處理,因為它表明代碼中存在一些嚴重的缺陷。其中最著名的是StackOverflowError(例如,當一個方法無休止地調用自身時會發生這種情況)和OutOfMemoryError(當沒有足夠的內存來創建新對象時會發生這種情況)。如您所見,在這些情況下,通常在運行時根本沒有什麼可處理的:代碼只是寫錯了,需要重新編寫。 異常- 這代表了一個異常:程序運行時發生的異常的、計劃外的情況。它們不像錯誤那麼嚴重,但它們仍然需要我們注意。所有異常都分為兩種類型:checkedunchecked例外:選中、未選中和自定義 - 3 所有已檢查的異常都派生自該類Exception。“檢查”是什麼意思?我們在上一課中提到了這一點: “Java 編譯器因此知道最常見的異常以及它們可能發生的情況。” 例如,它知道如果代碼從文件中讀取數據,則該文件很可能不存在。並且有很多這樣的情況(它可以推斷)。因此,編譯器會提前檢查我們的代碼是否存在這些潛在的異常。如果它找到它們,它不會編譯代碼,直到我們處理它們或重新拋出它們。第二種異常是“未檢查”。它們派生自RuntimeException類。它們與檢查異常有何不同?似乎也有很多不同的類派生自RuntimeException(描述運行時異常)。不同之處在於編譯器不會預料到這些錯誤。好像在說,“寫代碼的時候,我沒有發現任何可疑的地方,但是運行的時候出了問題,顯然是代碼有錯誤!” 的確如此。未經檢查的異常通常是程序員錯誤的結果。 而且編譯器顯然無法預見人們可能親手造成的每一種可能的不良情況。:) 因此,它不會檢查我們的代碼中是否處理了此類異常。您已經遇到過幾個未經檢查的異常:
  • 除以零時發生ArithmeticException
  • 當您嘗試訪問數組外的位置時,會發生ArrayIndexOutOfBoundsException 。
當然,您可以想像 Java 的創建者可以引入強制性的異常處理,但在這種情況下代碼會太複雜。對於任何除法運算,您是否必須編寫一個try-catch塊來檢查您是否不小心被零除了?任何時候你訪問一個數組,你都必須寫一個try-catch塊來檢查你的索引是否越界。一切都將是意大利麵條式代碼,並且將完全不可讀。放棄這個想法是有道理的。因此,未經檢查的異常不需要在try-catch塊中處理或重新拋出(儘管這在技術上是可行的,就像 Error 一樣)。

如何拋出自己的異常

當然,Java 的創造者不可能預見到程序中可能出現的每一個異常情況。世界上的程序太多了,而且種類繁多。但這沒什麼好擔心的,因為如果需要,您可以創建自己的異常。這很容易做到。您所要做的就是創建自己的課程。您應該確保其名稱以“Exception”結尾。編譯器不需要這個,但是閱讀你的代碼的其他程序員會立即明白它是一個​​異常類。另外,指明該類是從該類繼承的Exception(編譯器確實需要這樣做)。例如,假設我們有一個Dog類。我們可以使用walk()方法。但在此之前,我們需要檢查我們的寵物是否佩戴了項圈、皮帶和口套。如果缺少任何這些裝備,我們將拋出我們自己的異常:DogIsNotReadyException。它的代碼如下所示:

public class DogIsNotReadyException extends Exception {

   public DogIsNotReadyException(String message) {
       super(message);
   }
}
要表明該類是一個異常,需要在類名後寫“ extends Exception ”(意思是“該類派生自Exception類”)。在構造函數中,我們只需使用ExceptionString消息調用類構造函數(如果發生異常,我們將向用戶顯示消息,即錯誤描述)。這是我們的類代碼中的樣子:

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("We're getting ready for a walk!");
   if (isCollarPutOn && isLeashPutOn && isMuzzlePutOn) {
       System.out.println("Hooray, let's go for a walk! " + name + " is very happy!");
   } else {
       throw new DogIsNotReadyException(name + " is not ready for a walk! Check the gear!");
   }
 }

}
現在我們的walk()方法拋出DogIsNotReadyException。 這是通過關鍵字 throw 完成的。正如我們前面所說,異常是一個對象。因此,當我們的方法中發生異常(狗丟了東西)時,我們創建一個新DogIsNotReadyException對象並使用關鍵字 throw 將其拋出。我們將“ throws DogIsNotReadyException ”添加到方法聲明中。換句話說,現在編譯器知道調用該walk()方法可能會變成異常情況。因此,如果我們在程序的某處調用此方法,則必須處理此異常。讓我們嘗試在main()方法中這樣做:

public static void main(String[] args) {
  
   Dog dog = new Dog("Buddy");
   dog.putCollar();
   dog.putMuzzle();
   dog.walk();// Unhandled exception: DogIsNotReadyException
}
這不會編譯。異常未處理!我們將代碼包裝在一個try-catch塊中以處理異常:

public static void main(String[] args) {

   Dog dog = new Dog("Buddy");
   dog.putCollar();
   dog.putMuzzle();
   try {
       dog.walk();
   } catch (DogIsNotReadyException e) {
       System.out.println(e.getMessage());
       System.out.println("Checking the gear! Is the collar on? " + dog.isCollarPutOn + "\r\n Is the leash on? "
       + dog.isLeashPutOn + "\r\n Is the muzzle on? " + dog.isMuzzlePutOn);
   }
}
現在讓我們看看控制台輸出: 項圈打開了!槍口亮了!我們準備去散步了!Buddy 還沒準備好散步!檢查齒輪!檢查齒輪!衣領上了嗎?真的 系上皮帶了嗎?false 槍口是否打開?true 看看控制台輸出的信息量有多大!我們看到了計劃中的每一步;我們可以看到錯誤發生的位置,也可以立即準確地看到我們的狗丟失了什麼。:) 這就是您創建自己的異常的方式。如您所見,這並不復雜。即使 Java 的創造者沒有​​費心在語言中包含針對裝備不佳的狗的特殊例外,我們已經修復了他們的疏忽。:)

更多閱讀:

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION