CodeGym /課程 /JAVA 25 SELF /Java 例外的階層結構

Java 例外的階層結構

JAVA 25 SELF
等級 24 , 課堂 0
開放

1. 類別 Throwable:所有例外的根

接下來我們將詳細說明 Java 的例外系統:什麼是 ThrowableExceptionError 有何不同,以及「可檢查」與「非可檢查」例外代表什麼。這是在你的程式中正確處理錯誤的基礎。

在 Java 中,所有例外與錯誤都是從類別 java.lang.Throwable 繼承而來的物件。
Throwable 是整個 Java 問題處理階層的「始祖」。

示意:

Throwable
├── Exception
└── Error

Throwable 是在 Java 中可被「丟出」(throw)與「捕捉」(catch)的一切的基底類別。它無法直接使用——而是作為更具體錯誤型別的基礎。

Exception —— 用於「一般」錯誤

Exception 是所有在程式中可能發生、且可以也應該處理的例外的基底類別。這些是「工作層面」的錯誤:檔案、網路、輸入/輸出、使用者操作等問題。你大多數的 try-catch 都會處理 Exception 的子類別。

範例:

  • IOException —— 處理檔案或網路時的錯誤。
  • SQLException —— 存取資料庫時的錯誤。
  • FileNotFoundException —— 找不到檔案。

Error —— 用於 JVM 的致命錯誤

Error 是發生在 Java 虛擬機(JVM)層級的錯誤的基底類別。通常是嚴重的故障,程式無法也不應該處理。若發生 Error,應用程式多半無法繼續運作。

範例:

  • OutOfMemoryError —— 記憶體耗盡。
  • StackOverflowError —— 堆疊溢位(例如因為無限遞迴)。
  • NoClassDefFoundError —— 找不到所需的類別。

重要:
去捕捉並處理 Error 幾乎總是壞主意。這不是你的程式錯誤,而是執行環境的故障。

2. Checked vs Unchecked exceptions:這代表什麼?

在 Java 中,所有例外大致分為兩大類:

可檢查(Checked)例外

是什麼? 編譯器會強制你處理或明確向外拋出的例外。

何時出現? 通常與外部資源相關:檔案、網路、資料庫、使用者輸入。

如何處理? 不是用 try-catch 包起來,就是在方法簽章上加入 throws

範例: IOExceptionSQLExceptionFileNotFoundException

範例:

public void readFile(String path) throws IOException {
    FileReader reader = new FileReader(path); // 可能拋出 IOException
    // ...
}

若不處理或不往外拋出——程式將無法編譯!

非可檢查(Unchecked)例外

是什麼? 編譯器不要求必須處理的例外。

何時出現? 通常是程式邏輯錯誤:除以零、陣列越界、對 null 進行存取。

如何處理? 可以捕捉,但非必須。更好的作法是透過檢查來預防。

在階層中的位置? 全部都繼承自 RuntimeException

範例: NullPointerExceptionArrayIndexOutOfBoundsExceptionIllegalArgumentExceptionArithmeticException

範例:

int[] arr = {1, 2, 3};
System.out.println(arr[10]); // ArrayIndexOutOfBoundsException

編譯器不會強迫你捕捉這種例外——但一旦出錯,程式就會「當掉」。

3. 一張圖看懂整個階層

graph TD
    Throwable --> Error
    Throwable --> Exception
    
    Exception --> RuntimeException
    Exception --> CheckedExceptions["(其他 Checked Exceptions)"]
    
    Error --> OutOfMemoryError
    Error --> StackOverflowError
    
    RuntimeException --> NullPointerException
    RuntimeException --> IndexOutOfBoundsException
    RuntimeException --> IllegalArgumentException

    %% 樣式
    style Throwable fill:#ffa64d,color:#000
    style Exception fill:#ffa64d,color:#000
    style CheckedExceptions fill:#ffa64d,color:#000
    
    style Error fill:#ff4d4d,color:#fff
    style OutOfMemoryError fill:#ff4d4d,color:#fff
    style StackOverflowError fill:#ff4d4d,color:#fff
    
    style RuntimeException fill:#4dff88,color:#000
    style NullPointerException fill:#4dff88,color:#000
    style IndexOutOfBoundsException fill:#4dff88,color:#000
    style IllegalArgumentException fill:#4dff88,color:#000

表格:主要差異

類別 父類別 需要處理嗎? 範例
Checked Exception
Exception
IOException, SQLException
Unchecked
RuntimeException
NullPointerException, IndexOutOfBoundsException
Error
Error
OutOfMemoryError, StackOverflowError

4. 在程式碼中如何呈現?

Checked Exception:檔案範例

import java.io.*;

public class FileDemo {
    public static void main(String[] args) {
        try {
            FileReader reader = new FileReader("nofile.txt"); // FileNotFoundException (checked)
            int data = reader.read();
            System.out.println(data);
            reader.close();
        } catch (IOException e) {
            System.out.println("檔案操作發生錯誤: " + e.getMessage());
        }
    }
}

編譯器會要求你處理 IOException

Unchecked Exception:除以零的範例

public class ExceptionDemo {
    public static void main(String[] args) {
        int a = 10;
        int b = 0;
        int c = a / b; // ArithmeticException (unchecked)
        System.out.println("結果:" + c);
    }
}

編譯器不要求處理,但程式仍會「當掉」。

5. 為什麼需要例外階層?

  • 處理具有彈性: 你可以捕捉具體錯誤(FileNotFoundException),也可以捕捉整個族群(IOExceptionException)。
  • 程式碼可重用: 可以集中處理同一類型的錯誤。
  • 程式碼更乾淨: 主要邏輯不會被過多的細碎檢查淹沒。

範例:

try {
    // 危險的程式碼
} catch (FileNotFoundException e) {
    System.out.println("找不到檔案!");
} catch (IOException e) {
    System.out.println("輸入/輸出錯誤!");
} catch (Exception e) {
    System.out.println("出了點問題:" + e.getMessage());
}

6. 處理例外時的常見錯誤

錯誤 1:忽略例外。catch (Exception e) {} —— 不好!你會失去錯誤原因的資訊。

錯誤 2:捕捉過多。 catch (Exception e) 會把所有東西都抓住,甚至是未預期的。最好只捕捉你能處理的例外。

錯誤 3:去捕捉(Error)。 除非你在寫低階程式碼,否則不該捕捉 Error。那是 JVM 的問題,而不是你的程式。

錯誤 4:不區分 checked 與 unchecked。 例外不是一樣的!Checked 需要處理(Exception),Unchecked 則不需要(RuntimeException 及其子類)。

錯誤 5:沒有在例外中加入資訊。 若你自訂例外——務必加入具體且有用的訊息。

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