1. 認識例外
讓我們從一個簡單的類比開始。想像你的程式是一輛在道路上行駛的汽車。一切都很順利,直到突然發生了意料之外的情況:輪胎沒氣、汽油用盡、引擎過熱。如果不「處理」這些情況(例如換上備胎或去加油),汽車就會停下來,無法繼續前進。程式也是如此:如果不處理例外,程式就會異常終止。
例外 (exception) — 是在程式執行期間發生某個問題時建立的物件。例外會告訴你:「停!有些地方出了問題!」
產生例外的情況示例:
- 被零除(10 / 0)
- 嘗試存取不存在的陣列元素(arr[999])
- 開啟磁碟上不存在的檔案
- 將字串 "abc" 轉換為數字(Integer.parseInt("abc"))
重要: 例外不是編譯錯誤(例如程式碼中的打字錯誤),而是在程式執行期間才會發生的問題。
為什麼例外是好事?
- 程式碼更乾淨: 程式的主要邏輯不會被為了每件小事而進行的檢查所干擾。
- 更有彈性: 可以集中處理錯誤(例如,所有檔案讀取錯誤都在同一處理點)。
- 更可靠: 程式不會莫名其妙地「當掉」,而是會說明究竟發生了什麼。
2. 例外(Exceptions) vs 錯誤(Errors)
在 Java 中,程式執行時可能出現兩大類問題:
錯誤(Errors)
錯誤 是由於 Java 虛擬機(JVM)本身的運作故障而引發的致命、無法恢復的問題。通常與電腦資源或 JVM 的內部故障有關。
錯誤的示例:
- OutOfMemoryError — 記憶體用盡。
- StackOverflowError — 呼叫堆疊溢位(例如因無窮遞迴)。
重要: 這類錯誤通常不應在程式中嘗試處理。
例外(Exceptions)
例外 是程式可以(而且應該)處理的問題。它們可能由於程式邏輯錯誤或外部因素造成(例如使用者輸入了非預期的內容)。
例外的示例:
- NullPointerException — 嘗試把 null 當作物件來使用。
- ArrayIndexOutOfBoundsException — 陣列索引超出範圍。
- IOException — 檔案操作時發生錯誤。
Java 的例外分為兩種:
- Checked exceptions(受檢)— 編譯器要求必須處理它們(例如,IOException)。
- Unchecked exceptions(非受檢)— 編譯器不要求處理(例如,NullPointerException)。
示意圖:各類型的關係
graph TD
Throwable --> Error
Throwable --> Exception
Exception --> RuntimeException
Exception --> Checked["(其他 Exceptions)"]
style Throwable fill:#ffa64d,color:#000
style Exception fill:#ffa64d,color:#000
style Checked fill:#ffa64d,color:#000
style Error fill:#ff4d4d,color:#fff
style RuntimeException fill:#4dff88,color:#000
說明:
- Throwable — Java 中所有錯誤與例外的根類別。
- Error — JVM 的致命錯誤,不予處理。
- Exception — 「一般」例外,可以也應該被處理。
- RuntimeException — 非受檢例外(多為程式設計錯誤)。
3. 在程式碼中如何呈現?
範例 1:被零除
public class ExceptionDemo
{
public static void main(String[] args)
{
int a = 10;
int b = 0;
int c = a / b; // 這裡會拋出 ArithmeticException!
System.out.println("結果: " + c);
}
}
會發生什麼事?
程式會因錯誤而結束,並顯示如下訊息:
Exception in thread "main" java.lang.ArithmeticException: / by zero
at ExceptionDemo.main(ExceptionDemo.java:5)
範例 2:存取不存在的陣列元素
int[] arr = {1, 2, 3};
System.out.println(arr[10]); // ArrayIndexOutOfBoundsException
範例 3:檔案操作
import java.io.FileReader;
import java.io.IOException;
public class FileDemo
{
public static void main(String[] args) throws IOException
{
FileReader reader = new FileReader("nofile.txt"); // FileNotFoundException (checked)
int data = reader.read();
System.out.println(data);
reader.close();
}
}
接下來我們就來看看如何優雅地處理這些例外情況。
GO TO FULL VERSION