“嗨,阿米戈。今天我們要上一堂非常有趣的課。我要給你講講異常。異常是一種特殊的機制,可以讓我們處理程序中的錯誤。下面是一些可能發生的錯誤示例在程序中:

1. 當硬盤已滿時,程序可能會嘗試寫入文件。

2. 程序可能會嘗試在存儲空引用的變量上調用方法。

3. 程序可能會嘗試將一個數除以 0。"

所有這些操作都會導致錯誤。通常,結果是程序立即終止,因為在這種情況下繼續執行代碼是沒有意義的。

“為什麼?”

“如果汽車已經偏離道路並從懸崖上掉下來,繼續轉動車輪是否有意義?”

“那程序是不是應該停止運行了?”

“是的。至少,過去是這樣。任何錯誤都會導致程序終止。”

“這是一個非常聰明的方法。”

“但是嘗試並繼續運行該程序不是更好嗎?”

“是的。假設你在 Word 中鍵入了大量文本並保存了它。如果保存操作失敗,但程序讓你相信一切都很好怎麼辦?然後你繼續鍵入。那將是愚蠢的,不是嗎?”它?”

“是的。”

“然後程序員想出了一個有趣的解決方案:每個函數都會返回其工作狀態。0 意味著它按預期工作。任何其他值都意味著發生了一些錯誤,返回值是一個錯誤代碼。”

“但是,這種方法也有它的缺點。在每次(!)函數調用之後,您必須檢查返回代碼(數字)。首先,這很不方便:錯誤處理代碼很少執行,但需要包含在內無處不在。第二,函數經常返回不同的值——你應該用它們做什麼?”

“對啊,我也想過。”

“然後,一個光明的未來以異常和錯誤處理機制的形式出現了。它是這樣工作的:

1.當錯誤發生時,Java 機器創建一個特殊的對象——異常——它保存所有的錯誤信息。不同的錯誤有不同的異常。

2.異常導致程序立即退出當前函數,下一個函數等等——直到退出main方法。然後程序終止。程序員也可能會說 Java 機器‘展開了調用堆棧’。”

“但你說過程序並不總是終止。”

“是的,因為有一種方法可以捕獲異常。我們可以在正確的地方編寫特殊代碼來捕獲我們關心的異常並對其進行處理。這是很重要的事情。”

“為了幫助我們做到這一點,有一個特殊的try-catch結構。它是這樣工作的:”

捕獲異常(除以 0)並繼續工作的程序示例。
public class ExceptionExample2
{
    public static void main(String[] args)
    {
        System.out.println("Program starts");

        try
        {
            System.out.println("Before calling method1");
            method1();
            System.out.println("After calling method1. This will never be shown");
        }
        catch (Exception e)
        {
           System.out.println("Exception has been caught");
        }

        System.out.println("Program is still running");
    }

    public static void method1()
    {
        int a = 100;
        int b = 0;
        System.out.println(a / b);
    }
}
屏幕輸出:

Program starts
Before method1 calling
Exception has been caught
Program is still running

“但為什麼屏幕上不會顯示‘調用方法 1 之後。這將永遠不會顯示’?”

“很高興你提出這個問題。在第 25 行,我們除以 0,這會導致一個錯誤——一個異常。Java 機器創建一個包含錯誤信息的ArithmeticException 對象。該對象就是異常。

“異常發生在method1方法內部。這會導致方法立即終止。如果不是try-catch塊,它會導致main方法終止。”

“如果在try塊內發生異常,它會在catch塊中被捕獲。try塊中的其餘代碼將不會被執行。相反,catch塊將開始執行。

“我不明白。”

“換句話說,代碼是這樣工作的:

1、如果try塊內部發生異常,異常發生處的代碼停止執行,開始執行catch塊。

2.如果沒有異常發生,則try塊執行到結束不執行catch塊。

“嗯?”

“想像一下,在每次方法調用之後,我們檢查該方法是正常返回還是由於異常而突然終止。如果有異常,那麼我們將執行 catch 塊(如果有的話)以捕獲異常。如果沒有 catch 塊,那麼我們終止當前方法,調用我們的方法執行相同的檢查。”

“我想我現在明白了。”

“出色的。”

“catch 語句中的‘Exception’是什麼意思?”

"所有的異常都是繼承Exception類的類。我們可以通過在catch塊中指定異常類來捕獲特定的異常,也可以通過指定它們的共同父類——Exception來捕獲所有的異常。這樣我們就可以獲得所有必要的錯誤來自變量 e 的信息(它存儲對異常對象的引用)。”

“酷!如果我的方法中出現了不同的異常,那麼我可以對它們進行不同的處理嗎?”

“你不僅可以,而且你應該這樣做。你可以這樣做:”

例子:
public class ExceptionExample2
{
    public static void main(String[] args)
    {
        System.out.println("Program starts");

        try
        {
            System.out.println("Before calling method1");
            method1();
            System.out.println("After calling method1. This will never be shown");
        }
        catch (NullPointerException e)
        {
           System.out.println("Null reference. Exception has been caught");
        }
        catch (ArithmeticException e)
        {
            System.out.println("Division by zero. Exception has been caught");
        }
        catch (Exception e)
        {
            System.out.println("Any other errors. Exception has been caught");
        }

        System.out.println("Program is still running");
    }

    public static void method1()
    {
        int a = 100;
        int b = 0;
        System.out.println(a / b);
    }
}

try塊可以與多個catch塊配對,每個 catch 塊都會捕獲指定類型的異常。”

“我想我明白了。我還不能自己寫這個,但如果我在代碼中遇到它,我就不會害怕了。”