Java異常類層次結構?
- Throwable 是 Java 語言中所有錯誤與異常的超類。
- Error 類及其子類:程式中無法處理的錯誤,表示運作應用程式中出現了嚴重的錯誤。
- Exception 程式本身可以捕獲并且可以處理的異常。Exception 這種異常又分為兩類:運作時異常和編譯時異常。
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAnYldHL0FWby9mZvwFN4ETMfdHLkVGepZ2XtxSZ6l2clJ3LcV2Zh1Wa9M3clN2byBXLzN3btgHL9s2RkBnVHFmb1clWvB3MaVnRtp1XlBXe0xCMy81dvRWYoNHLwEzX5xCMx8FesU2cfdGLwMzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsQTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5CMwIzN4QTZ0ADZ0IzNjBjNzYzXwQzMxUTMxAzLcFTMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.png)
- 運作時異常
都是RuntimeException類及其子類異常,如NullPointerException(空指針異常)、IndexOutOfBoundsException(下标越界異常)等,這些異常是不檢查異常,程式中可以選擇捕獲處理,也可以不處理。這些異常一般是由程式邏輯錯誤引起的,程式應該從邏輯角度盡可能避免這類異常的發生。
運作時異常的特點是Java編譯器不會檢查它,也就是說,當程式中可能出現這類異常,即使沒有用try-catch語句捕獲它,也沒有用throws子句聲明抛出它,也會編譯通過。
- 非運作時異常 (編譯異常)
是RuntimeException以外的異常,類型上都屬于Exception類及其子類。從程式文法角度講是必須進行處理的異常,如果不處理,程式就不能編譯通過。如IOException、SQLException等以及使用者自定義的Exception異常,一般情況下不自定義檢查異常。
可查的異常(checked exceptions)和不可查的異常(unchecked exceptions)差別?
- 可查異常(編譯器要求必須處置的異常):
正确的程式在運作中,很容易出現的、情理可容的異常狀況。可查異常雖然是異常狀況,但在一定程度上它的發生是可以預計的,而且一旦發生這種異常狀況,就必須采取某種方式進行處理。
除了RuntimeException及其子類以外,其他的Exception類及其子類都屬于可查異常。這種異常的特點是Java編譯器會檢查它,也就是說,當程式中可能出現這類異常,要麼用try-catch語句捕獲它,要麼用throws子句聲明抛出它,否則編譯不會通過。
- 不可查異常(編譯器不要求強制處置的異常)
包括運作時異常(RuntimeException與其子類)和錯誤(Error)。
throw和throws的差別?
- 異常的申明(throws)
在Java中,目前執行的語句必屬于某個方法,Java解釋器調用main方法執行開始執行程式。若方法中存在檢查異常,如果不對其捕獲,那必須在方法頭中顯式聲明該異常,以便于告知方法調用者此方法有異常,需要進行處理。 在方法中聲明一個異常,方法頭中使用關鍵字throws,後面接上要聲明的異常。若聲明多個異常,則使用逗号分割。如下所示:
public static void method() throws IOException, FileNotFoundException{
//something statements
}
- 異常的抛出(throw)
如果代碼可能會引發某種錯誤,可以建立一個合适的異常類執行個體并抛出它,這就是抛出異常。如下所示:
public static double method(int value) {
if(value == 0) {
throw new ArithmeticException("參數不能為0"); //抛出一個運作時異常
}
return 5.0 / value;
}
Java 7 的 try-with-resource?
如果你的資源實作了 AutoCloseable 接口,你可以使用這個文法。大多數的 Java 标準資源都繼承了這個接口。當你在 try 子句中打開資源,資源會在 try 代碼塊執行後或異常處理後自動關閉。
public void automaticallyCloseResource() {
File file = new File("./tmp.txt");
try (FileInputStream inputStream = new FileInputStream(file);) {
// use the inputStream to read a file
} catch (FileNotFoundException e) {
log.error(e);
} catch (IOException e) {
log.error(e);
}
}
異常的底層?
提到JVM處理異常的機制,就需要提及Exception Table,以下稱為異常表。我們暫且不急于介紹異常表,先看一個簡單的 Java 處理異常的小例子。
public static void simpleTryCatch() {
try {
testNPE();
} catch (Exception e) {
e.printStackTrace();
}
}
使用javap來分析這段代碼(需要先使用javac編譯)
//javap -c Main
public static void simpleTryCatch();
Code:
0: invokestatic #3 // Method testNPE:()V
3: goto 11
6: astore_0
7: aload_0
8: invokevirtual #5 // Method java/lang/Exception.printStackTrace:()V
11: return
Exception table:
from to target type
0 3 6 Class java/lang/Exception
看到上面的代碼,應該會有會心一笑,因為終于看到了Exception table,也就是我們要研究的異常表。
- from 可能發生異常的起始點
- to 可能發生異常的結束點
- target 上述from和to之前發生異常後的異常處理者的位置
- type 異常處理者處理的異常的類資訊