例外處理概述
在 Java 中,例外(Exception)是指在程式執行過程中發生的異常情況。例外處理是一種機制,用來捕捉和處理這些異常情況,確保程式的正常運行。
例外的種類
Java 中的例外主要分為兩類:
- 檢查型例外(Checked Exception):在編譯時必須處理的例外,例如
IOException 和 SQLException。
- 非檢查型例外(Unchecked Exception):在運行時可能發生的例外,例如
NullPointerException 和 ArrayIndexOutOfBoundsException。
例外處理的基本語法
Java 提供了 try-catch 語句來捕捉和處理例外。基本語法如下:
1 2 3 4 5 6 7
| try { } catch (ExceptionType e) { } finally { }
|
使用 try-catch 進行例外處理
以下是一個例子,示範如何使用 try-catch 來處理例外:
1 2 3 4 5 6 7 8 9 10 11
| public class ExceptionExample { public static void main(String[] args) { try { int[] numbers = {1, 2, 3}; System.out.println(numbers[3]); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("例外類型:" + e.getClass().getName()); System.out.println("錯誤訊息:" + e.getMessage()); } } }
|
最終區塊 finally
finally 區塊用於執行清理工作,如關閉檔案或釋放資源。無論是否發生例外,finally 區塊中的程式碼都會執行。
1 2 3 4 5 6 7 8 9 10 11
| public class FinallyExample { public static void main(String[] args) { try { int result = 10 / 0; } catch (ArithmeticException e) { System.out.println("除以零的錯誤:" + e.getMessage()); } finally { System.out.println("這個區塊會執行。"); } } }
|
自訂例外
可以透過繼承 Exception 類別來創建自訂例外。以下是一個簡單的範例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| class MyException extends Exception {
public MyException(String message) { super(message); } }
public class CustomExceptionExample { public static void main(String[] args) { try { throw new MyException("這是一個自訂例外!"); } catch (MyException e) { System.out.println(e.getMessage()); } } }
|
補充展開:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public class Throwable implements java.io.Serializable { private String detailMessage;
public Throwable(String message) { detailMessage = message; }
public String getMessage() { return detailMessage; } }
public class Exception extends Throwable { public Exception(String message) { super(message); } }
class MyException extends Exception { public MyException(String message) { super(message); } }
public class CustomExceptionExample { public static void main(String[] args) { try { throw new MyException("這是一個自訂例外!"); } catch (MyException e) { System.out.println(e.getMessage()); } } }
|
1 2 3 4 5 6 7 8
| Throwable ├── Exception │ ├── RuntimeException (運行時異常/非檢查異常) │ │ ├── ArithmeticException │ │ ├── ArrayIndexOutOfBoundsException │ │ └── InputMismatchException │ └── IOException (檢查異常) └── Error
|
例外的傳遞
當一個方法拋出例外時,可以選擇將例外傳遞給呼叫者。透過 throws 關鍵字來實現:
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class ThrowExample { public static void mayThrowException() throws Exception { throw new Exception("可能發生的例外"); }
public static void main(String[] args) { try { mayThrowException(); } catch (Exception e) { System.out.println("捕捉到例外:" + e.getMessage()); } } }
|
程式流程
try 裡呼叫 mayThrowException()。
mayThrowException() 主動丟出一個新的 Exception,訊息是 “可能發生的例外”。
- 這個
Exception 立刻「拋出」回呼叫它的地方,也就是 try。
- 因為
try 內程式丟出 Exception,會直接跳到 catch(Exception e) 來捕捉這個錯誤。
catch 裡用 e.getMessage() 取得這個例外的訊息並印出。
例外處理的建議
- 儘量使用
try-catch 來處理可能發生的例外。
- 只捕捉需要處理的例外,不要使用
catch (Exception e) 捕捉所有例外。
- 在
finally 區塊中釋放資源。
- 自訂例外時,提供有意義的錯誤訊息。
常見 Exception 與 Error 對照表
| 類型 |
說明 / 觸發時機 |
範例程式碼(簡略) |
| ArithmeticException |
數學錯誤,如除以零 |
int x = 10 / 0; |
| ArrayIndexOutOfBoundsException |
陣列索引超出範圍 |
arr[3] = 5; |
| ClassCastException |
錯誤的類型轉型 |
(Integer)(Object)"abc"; |
| ConcurrentModificationException |
遍歷時修改集合 |
for-each + remove() |
| EOFException |
資料讀取超過結尾(串流) |
readObject(); |
| FileNotFoundException |
檔案不存在 |
new FileReader("abc.txt"); |
| IllegalArgumentException |
傳入非法參數 |
Thread.sleep(-1); |
| IllegalStateException |
呼叫不合時機的方法 |
scanner.nextLine(); // close後 |
| IndexOutOfBoundsException |
索引越界(泛用) |
list.get(99); |
| InputMismatchException |
輸入與預期型別不符 |
scanner.nextInt(); // 輸入abc |
| InterruptedException |
執行緒睡眠或等待時被中斷 |
Thread.sleep(1000); |
| IOException |
I/O 錯誤(讀檔、寫檔) |
reader.readLine(); |
| NegativeArraySizeException |
建立負長度陣列 |
new int[-3]; |
| NoSuchElementException |
無元素可讀取 |
scanner.nextLine(); // 無輸入 |
| NullPointerException |
呼叫 null 物件的方法或欄位 |
s.length(); // s 是 null |
| NumberFormatException |
字串無法轉成數字 |
Integer.parseInt("abc"); |
| SecurityException |
違反安全管理(例如反射) |
System.setSecurityManager(...) |
| StackOverflowError (非 Exception) |
遞迴過深導致堆疊爆炸 |
infiniteRecursion(); |
| StringIndexOutOfBoundsException |
字串索引錯誤 |
"abc".charAt(5); |
| UnsupportedOperationException |
呼叫未支援的方法 |
List.of(1,2).add(3); |
| OutOfMemoryError (非 Exception) |
記憶體不足 |
while(true) list.add(new int[999999]); |
類型區分補充:
| 類型分類 |
說明 |
範例 |
| Checked Exception |
編譯時需處理,用 try-catch 或 throws |
IOException, FileNotFoundException |
| Unchecked Exception |
執行時錯誤,編譯器不強制處理 |
NullPointerException, ArithmeticException |
| Error |
嚴重錯誤,通常不處理 |
StackOverflowError, OutOfMemoryError |