你好,我是 Guide。秋招即將到來,我對 JavaGuide 的內容進行了重構完善,同步一下最新更新,希望能夠幫助你。
前兩篇:
Java 異常類層次結構圖概覽 :
在 Java 中,所有的異常都有一個共同的祖先 java.lang
包中的 Throwable
類。Throwable
類有兩個重要的子類:
Exception
:程式本身可以處理的異常,可以通過 catch
來進行捕獲。Exception
又可以分為 Checked Exception (受檢查異常,必須處理) 和 Unchecked Exception (不受檢查異常,可以不處理)。Error
:Error
屬於程式無法處理的錯誤 ,catch
來進行捕獲catch
捕獲 。例如 Java 虛擬機器器執行錯誤(Virtual MachineError
)、虛擬機器器記憶體不夠錯誤(OutOfMemoryError
)、類定義錯誤(NoClassDefFoundError
)等 。這些異常發生時,Java 虛擬機器器(JVM)一般會選擇執行緒終止。Checked Exception 即 受檢查異常 ,Java 程式碼在編譯過程中,如果受檢查異常沒有被 catch
或者throws
關鍵字處理的話,就沒辦法通過編譯。
比如下面這段 IO 操作的程式碼:
除了RuntimeException
及其子類以外,其他的Exception
類及其子類都屬於受檢查異常 。常見的受檢查異常有: IO 相關的異常、ClassNotFoundException
、SQLException
...。
Unchecked Exception 即 不受檢查異常 ,Java 程式碼在編譯過程中 ,我們即使不處理不受檢查異常也可以正常通過編譯。
RuntimeException
及其子類都統稱為非受檢查異常,常見的有(建議記下來,日常開發中會經常用到):
NullPointerException
(空指標錯誤)IllegalArgumentException
(引數錯誤比如方法入參型別錯誤)NumberFormatException
(字串轉換為數位格式錯誤,IllegalArgumentException
的子類)ArrayIndexOutOfBoundsException
(陣列越界錯誤)ClassCastException
(型別轉換錯誤)ArithmeticException
(算術錯誤)SecurityException
(安全錯誤比如許可權不夠)UnsupportedOperationException
(不支援的操作錯誤比如重複建立同一使用者)String getMessage()
: 返回異常發生時的簡要描述String toString()
: 返回異常發生時的詳細資訊String getLocalizedMessage()
: 返回異常物件的在地化資訊。使用 Throwable
的子類覆蓋這個方法,可以生成在地化資訊。如果子類沒有覆蓋該方法,則該方法返回的資訊與 getMessage()
返回的結果相同void printStackTrace()
: 在控制檯上列印 Throwable
物件封裝的異常資訊try
塊 : 用於捕獲異常。其後可接零個或多個 catch
塊,如果沒有 catch
塊,則必須跟一個 finally
塊。catch
塊 : 用於處理 try 捕獲到的異常。finally
塊 : 無論是否捕獲或處理異常,finally
塊裡的語句都會被執行。當在 try
塊或 catch
塊中遇到 return
語句時,finally
語句塊將在方法返回之前被執行。程式碼範例:
try {
System.out.println("Try to do something");
throw new RuntimeException("RuntimeException");
} catch (Exception e) {
System.out.println("Catch Exception -> " + e.getMessage());
} finally {
System.out.println("Finally");
}
輸出:
Try to do something
Catch Exception -> RuntimeException
Finally
注意:不要在 finally 語句塊中使用 return! 當 try 語句和 finally 語句中都有 return 語句時,try 語句塊中的 return 語句會被忽略。這是因為 try 語句中的 return 返回值會先被暫存在一個本地變數中,當執行到 finally 語句中的 return 之後,這個本地變數的值就變為了 finally 語句中的 return 返回值。
jvm 官方檔案中有明確提到:
If the
try
clause executes a return, the compiled code does the following:
- Saves the return value (if any) in a local variable.
- Executes a jsr to the code for the
finally
clause.- Upon return from the
finally
clause, returns the value saved in the local variable.
程式碼範例:
public static void main(String[] args) {
System.out.println(f(2));
}
public static int f(int value) {
try {
return value * value;
} finally {
if (value == 2) {
return 0;
}
}
}
輸出:
0
不一定的!在某些情況下,finally 中的程式碼不會被執行。
就比如說 finally 之前虛擬機器器被終止執行的話,finally 中的程式碼就不會被執行。
try {
System.out.println("Try to do something");
throw new RuntimeException("RuntimeException");
} catch (Exception e) {
System.out.println("Catch Exception -> " + e.getMessage());
// 終止當前正在執行的Java虛擬機器器
System.exit(1);
} finally {
System.out.println("Finally");
}
輸出:
Try to do something
Catch Exception -> RuntimeException
另外,在以下 2 種特殊情況下,finally
塊的程式碼也不會被執行:
相關 issue: https://github.com/Snailclimb/JavaGuide/issues/190。