在 Java 里,異常體系是其錯誤處理機制的核心內容,它能夠幫助開發者有效應對程序運行時出現的各種意外狀況。
異常體系的基本架構
它主要包含兩個重要分支:
- Error(錯誤):這類異常是程序自身無法處理的嚴重問題,像
OutOfMemoryError
和StackOverflowError
就屬于此類。一般而言,開發者不需要針對這類異常編寫特別的處理代碼。 - Exception(異常):這是程序在運行過程中能夠捕獲和處理的異常。它又可以進一步細分為:
- 受檢查異常(Checked Exception):這類異常在編譯階段就會被檢查,例如
IOException
和SQLException
。程序必須對它們進行捕獲或者聲明拋出。 - 運行時異常(RuntimeException):也被稱作非受檢查異常,像
NullPointerException
和ArrayIndexOutOfBoundsException
都屬于此類。編譯時不會強制要求處理這類異常。
- 受檢查異常(Checked Exception):這類異常在編譯階段就會被檢查,例如
?
?Error
在 Java 中,Error是Throwable
類的子類,用于表示系統級的嚴重故障,通常無法通過程序恢復。
一、特點
- 不可恢復:表示 JVM 或系統級的嚴重問題,程序通常無法處理。
- 不強制捕獲:編譯器不會檢查 Error,也不要求代碼處理它。
- 避免捕獲:捕獲 Error 可能導致程序進入不穩定狀態。
二、常見的 Error 類型
1.?內存相關錯誤
OutOfMemoryError
:內存不足,無法分配對象。
// 示例:創建過大的數組可能導致OutOfMemoryError
byte[] array = new byte[Integer.MAX_VALUE];
?StackOverflowError
:方法調用棧深度超過限制(常見于遞歸無終止條件)。
// 示例:無限遞歸導致StackOverflowError
public void recursive() {recursive(); // 最終棧溢出
}
2.?類加載相關錯誤
NoClassDefFoundError
:編譯時存在的類,運行時找不到(如依賴庫缺失)。ClassFormatError
:類文件格式錯誤(如.class 文件損壞)。
3.?JVM 內部錯誤
InternalError
:JVM 內部發生錯誤(如 JIT 編譯器故障)。VirtualMachineError
:JVM 崩潰或無法繼續運行的嚴重錯誤。
Exception
受檢查異常(Checked Exception)
特點:
- 在編譯階段就會被編譯器檢查。
- 程序必須對這類異常進行處理,處理方式有兩種:要么使用
try-catch
語句捕獲,要么在方法簽名中用throws
聲明拋出。 - 一般是由程序外部的因素引發的,比如文件系統、網絡或者數據庫等出現問題。
常見示例:
- IOException:在進行輸入輸出操作時,如果出現錯誤,就會拋出此異常。例如,嘗試讀取一個不存在的文件時。
- SQLException:在訪問數據庫時,如果出現錯誤,會引發該異常。比如 SQL 語句執行失敗。
- ClassNotFoundException:當使用反射機制加載類,卻找不到指定的類時,會產生此異常。
- InterruptedException:當一個線程被另一個線程中斷時,會拋出此異常。
處理方式?
import java.io.FileInputStream;
import java.io.IOException;public class CheckedExceptionExample {public static void main(String[] args) {try {readFile(); // 必須捕獲或聲明拋出} catch (IOException e) {e.printStackTrace();}}public static void readFile() throws IOException {FileInputStream file = new FileInputStream("non_existent_file.txt");}
}
運行時異常(RuntimeException)
特點:
- 屬于
RuntimeException
的子類。 - 編譯時不會強制要求處理這類異常,也就是說可以不捕獲,也不用在方法簽名中聲明。
- 通常是由程序中的邏輯錯誤導致的,比如空指針引用、數組越界等。
常見示例:
- NullPointerException:當嘗試訪問空對象的方法或屬性時會拋出此異常
String str = null;
System.out.println(str.length()); // 拋出NullPointerException
??????2.ArrayIndexOutOfBoundsException:訪問數組時,如果使用的索引超出了數組的有效范圍,就會引發該異常。
int[] arr = new int[5];
System.out.println(arr[10]); // 拋出ArrayIndexOutOfBoundsException
??????3.ArithmeticException:進行數學運算時,若出現非法操作,比如除以零,就會拋出此異常。
int result = 10 / 0; // 拋出ArithmeticException
??????4.IllegalArgumentException:當傳入的參數不符合方法的要求時,會產生該異常。
public void setAge(int age) {if (age < 0) {throw new IllegalArgumentException("年齡不能為負數");}
}
?
?受檢查異常 vs 運行時異常
對比項 | 受檢查異常(Checked Exception) | 運行時異常(RuntimeException) |
---|---|---|
編譯時檢查 | 必須處理,否則編譯不通過 | 不強制要求處理 |
繼承關系 | 繼承自Exception 類(但不包括RuntimeException ) | 繼承自RuntimeException 類 |
常見場景 | 外部資源訪問(文件、網絡、數據庫等) | 程序邏輯錯誤(空指針、數組越界等) |
處理方式 | 捕獲(try-catch)或聲明拋出(throws) | 可不處理,通過代碼邏輯避免 |
異常和錯誤的區別
對比項 | 異常(Exception) | 錯誤(Error) |
---|---|---|
設計目的 | 表示程序可處理的意外情況,如文件不存在、網絡中斷。 | 表示系統級不可恢復的嚴重故障,如內存溢出、棧溢出。 |
處理要求 | 受檢查異常必須被捕獲或聲明拋出; 運行時異常可選擇性處理。 | 通常不捕獲,也不應該嘗試處理,而是讓程序終止。 |
常見子類 | IOException ,?SQLException ,?NullPointerException | OutOfMemoryError ,?StackOverflowError ,?NoClassDefFoundError |
代碼示例 | java<br>try {<br> FileInputStream file = new FileInputStream("test.txt");<br>} catch (FileNotFoundException e) {<br> e.printStackTrace();<br>}<br> | java<br>public void recursive() {<br> recursive(); // 最終導致StackOverflowError<br>}<br> |