每個 Java 範例都是獨立的 Main.java,可用 JDK 11 編譯執行;請一次複製一個範例。題庫使用 public class Solution 中的 public static solve(...) 方法,請保留題目指定的型別與參數,使用 return 交回答案,不必另外讀取輸入或撰寫 main。
01|先辨認是哪一種錯誤
教材將 bug 分成編譯時期、執行時期與商業邏輯三類。少分號、型別不合等錯誤由編譯器指出;陣列越界或不合法轉型可能在執行時拋出例外;公式或邊界判斷寫錯,則可能正常執行卻得到錯答案。
- 編譯錯誤:先找第一個錯誤位置,修正語法、名稱、型別或 import。
- 執行例外:讀例外類別、訊息與 stack trace,找出最接近錯誤來源的自寫程式行。
- 邏輯錯誤:用已知答案、小資料與邊界案例核對;try/catch 不會修正錯誤的計算公式。
教材對照:PDF 第 2 頁
02|Throwable、Error 與 Exception
Throwable 是可被拋出物件的根型別,主要分成 Error 與 Exception。RuntimeException 及其子類別、Error 及其子類別屬於 unchecked;其餘例外類別屬於 checked。例如 IOException 是 checked,ArithmeticException 與 NullPointerException 是 unchecked。
- checked exception:呼叫可能拋出的操作時,必須捕捉,或在方法上用 throws 宣告向外傳遞。
- unchecked exception:編譯器不強制 catch/throws;仍應檢查不合法狀態與修正程式。
- Error 通常表示 JVM 或資源等嚴重問題;不要用 catch(Throwable) 把所有錯誤都當成一般輸入問題吞掉。
教材對照:PDF 第 3–5、12–13 頁
03|try 與 catch 的執行路線
try 放可能失敗的操作。例外發生時,try 中後續敘述會被跳過,改找型別匹配的 catch。catch 處理完成後,再接著執行整組 try/catch 後面的程式。例外物件的 getMessage 可取說明,printStackTrace 可顯示呼叫路徑。
public class Main {
public static void main(String[] args) {
int divisor = 0;
try {
System.out.println(20 / divisor);
System.out.println("這行不會執行");
} catch (ArithmeticException error) {
System.out.println("無法進行整數除法");
}
System.out.println("繼續執行");
}
}無法進行整數除法 繼續執行
教材對照:PDF 第 6–10 頁
04|多個 catch 由具體到一般
若多個 catch 有繼承關係,子類別要放前面,否則會先被父類別接走,讓後面的 catch 無法到達。每次例外只會進入第一個匹配的 catch。沒有繼承關係的例外也可以在相同處理方式時使用 multi-catch,以 | 分隔。
public class Main {
public static void main(String[] args) {
String[] texts = {"12", "bad", null};
for (String text : texts) {
try {
System.out.println(Integer.parseInt(text.trim()));
} catch (NumberFormatException error) {
System.out.println("數字格式錯誤");
} catch (RuntimeException error) {
System.out.println("其他執行例外");
}
}
}
}12 數字格式錯誤 其他執行例外
教材對照:PDF 第 6–10 頁
05|finally 與 return 的先後
finally 用於離開 try/catch 時的收尾。不論正常完成、例外或 return,通常都會先執行 finally。若 JVM 被終止、程序遭強制停止等,則不能保證它會執行。不要在 finally 寫 return 或拋出新例外,以免蓋掉原本結果。
public class Main {
static int calculate() {
try {
System.out.println("開始");
return 7;
} finally {
System.out.println("收尾");
}
}
public static void main(String[] args) {
System.out.println(calculate());
}
}開始 收尾 7
教材對照:PDF 第 11–13 頁
06|Java 11 補充:自動關閉資源
檔案、串流等資源常需要 close。Java 11 的 try-with-resources 可管理 AutoCloseable 資源,在離開區塊時自動關閉,即使中途拋出例外也會處理。這是將教材 finally 收尾觀念用在 Java 11 的實用寫法。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
try (Scanner scanner = new Scanner("12 8")) {
int total = scanner.nextInt() + scanner.nextInt();
System.out.println(total);
}
System.out.println("Scanner 已關閉");
}
}20 Scanner 已關閉
教材對照:PDF 第 11–13(資源管理延伸) 頁
07|Call Stack:例外向呼叫者傳遞
目前方法沒有匹配的 catch 時,例外會沿著呼叫鏈向外傳遞,直到找到處理者。呼叫失敗後的敘述不會繼續執行;若最後仍未處理,該執行緒會終止並回報例外。閱讀 stack trace 時,先找到拋出處,再往上找呼叫來源。
public class Main {
static void readScore() {
parseScore();
System.out.println("此行不會執行");
}
static void parseScore() {
Integer.parseInt("abc");
}
public static void main(String[] args) {
try {
readScore();
} catch (NumberFormatException error) {
System.out.println("main 收到格式錯誤");
}
}
}main 收到格式錯誤
教材對照:PDF 第 14–15 頁
08|throw、throws 與自訂例外
throw 實際拋出一個例外物件;throws 寫在方法宣告中,告訴呼叫者可能向外傳遞哪些例外。自訂 checked exception 可繼承 Exception;訊息傳給 super(message),呼叫者就能使用 getMessage 取得。
public class Main {
static class InvalidScoreException extends Exception {
InvalidScoreException(String message) {
super(message);
}
}
static void register(int score) throws InvalidScoreException {
if (score < 0 || score > 100) {
throw new InvalidScoreException("分數必須介於 0 到 100");
}
System.out.println("分數=" + score);
}
public static void main(String[] args) {
try {
register(-1);
} catch (InvalidScoreException error) {
System.out.println(error.getMessage());
}
}
}分數必須介於 0 到 100
教材對照:PDF 第 16–19 頁
WHEN SOMETHING GOES WRONG
遇到錯誤,先檢查這裡
catch(Exception) 放在所有 catch 最前面
會遮住後面的子類別處理。先處理具體例外,再按需要處理較一般的例外。
以為 throws 就已經處理失敗
throws 讓責任往呼叫者傳遞;真正處理需要 catch 內的行為,或由更外層決定如何回應。
捕捉後什麼都不做,仍假裝成功
定義清楚失敗時應回傳、回報或停止的規則,保留必要訊息,不要讓錯誤結果繼續流入後續計算。
PAUSE AND TRY
先不要急著看別人的寫法
- 把第三節的 divisor 改成 4,哪些行會執行?
- 如果 finally 列印後,呼叫者才列印回傳值,輸出順序如何推導?
- 將 register(-1) 改成 register(100) 與 register(101),比較成功與失敗路線。
先用紙筆預測,再改動範例中的數字或文字。結果與預期不同時,找出最早開始不同的那一步。
把這幾件事帶走
- 先讀例外類型,再決定處理方式。
- catch 處理失敗,finally 收尾,throws 宣告傳遞。
- 邊界檢查與例外處理各有用途,不能取代正確的程式邏輯。
FROM READING TO PRACTICE
用三道免費題,練習本章觀念
先做簡單題確認語法,再把幾個步驟組合起來。三題都來自本章主題的 Java 免費題庫,難度表示需要組合的基本概念。
教材來源與 Java 11 對照
本章依據《第二部分 04 Java 例外處理機制.pdf》PDF 第 2–19 頁整理,將原有觀念重新編寫為可閱讀與執行的網站教學。頁碼為 PDF 檔案頁次;舊版語法說明與已知誤植依 Java 11 修正,補充內容另有標示。
需要查閱更完整的規則時,可參考以下官方文件。