checked和unchecked異常
-
checked 異常(檢查型異常)在原始碼裡必須顯式地捕獲或者丟擲,否則編譯器會提示你進行相應的操作;而 unchecked 異常(非檢查型異常)就是所謂的執行時異常,通常是可以透過編碼進行規避的,並不需要顯式地捕獲或者丟擲。
-
NoClassDefFoundError:程式在編譯時可以找到所依賴的類,但是在執行時找不到指定的類檔案,導致丟擲該錯誤;原因可能是 jar 包缺失或者呼叫了初始化失敗的類。
-
ClassNotFoundException:當動態載入 Class 物件的時候找不到對應的類時丟擲該異常;原因可能是要載入的類不存在或者類名寫錯了。
throw和throws
1)throws關鍵字用於宣告異常,它的作用和try-catch相似;而throw關鍵字用於顯式的丟擲異常。
throws ArithmeticException;
2)throws關鍵字後面跟的是異常的名字;而throw關鍵字後面跟的是異常的物件。
throw new ArithmeticException("算術異常");
3)throws關鍵字出現在方法簽名上,而throw關鍵字出現在方法體裡。
4)throws關鍵字在宣告異常的時候可以跟多個,用逗號隔開;而throw關鍵字每次只能丟擲一個異常。
- 如果有好幾個類似的方法都可能出現異常,如果為每個方法都加上try-catch,就會顯得非常繁瑣。一個解決辦法就是,使用throws關鍵字,在方法簽名上宣告可能會丟擲的異常,然後在呼叫該方法的地方使用try-catch進行處理。
public static void main(String args[]){
try {
myMethod1();
} catch (ArithmeticException e) {
// 算術異常
} catch (NullPointerException e) {
// 空指標異常
}
}
public static void myMethod1() throws ArithmeticException, NullPointerException{
// 方法簽名上宣告異常
}
try-catch-finally
-
一個
try
塊後面可以跟多個catch
塊,用來捕獲不同型別的異常並做相應的處理,當 try 塊中的某一行程式碼發生異常時,之後的程式碼就不再執行,而是會跳轉到異常對應的 catch 塊中執行。 -
如果一個 try 塊後面跟了多個與之關聯的 catch 塊,那麼應該把特定的異常放在前面,通用型的異常放在後面,不然編譯器會提示錯誤。
-
finally 塊前面必須有 try 塊,不要把 finally 塊單獨拉出來使用。編譯器也不允許這樣做。
-
finally 塊不是必選項,有 try 塊的時候不一定要有 finally 塊。
-
如果 finally 塊中的程式碼可能會發生異常,也應該使用 try-catch 進行包裹。
-
即便是 try 塊中執行了 return、break、continue 這些跳轉語句,finally 塊也會被執行
-
不執行finally的情況:遇到了死迴圈;執行了
System. exit()
這行程式碼。
class MyFinallyReadLineThrow {
public void close() throws Exception {
throw new Exception("close");
}
public void readLine() throws Exception {
throw new Exception("readLine");
}
}
public class Test {
public static void main(String[] args) throws Exception {
MyFinallyReadLineThrow myThrow = null;
try {
myThrow = new MyFinallyReadLineThrow();
// readLine的異常資訊丟失
myThrow.readLine();
} finally {
myThrow.close();
}
/*
Exception in thread "main" java.lang.Exception: close
at test.ExceptionTest.MyFinallyReadLineThrow.close(Test.java:5)
at test.ExceptionTest.Test.main(Test.java:21)
*/
}
}
try-with-resources
- 當一個異常被丟擲的時候,可能有其他異常因為該異常而被抑制住,從而無法正常丟擲。這時可以透過
addSuppressed()
方法把這些被抑制的方法記錄下來,然後被抑制的異常就會出現在丟擲的異常的堆疊資訊中,可以透過getSuppressed()
方法來獲取這些異常。這樣做的好處是不會丟失任何異常,方便我們進行除錯。
package test.ExceptionTest;
class MyFinallyReadLineThrow implements AutoCloseable {
@Override
public void close() throws Exception {
throw new Exception("close");
}
public void readLine() throws Exception {
throw new Exception("readLine");
}
}
public class Test {
public static void main(String[] args) {
try (MyFinallyReadLineThrow myThrow = new MyFinallyReadLineThrow()) {
myThrow.readLine();
} catch (Exception e) {
e.printStackTrace();
}
/*
java.lang.Exception: readLine
at test.ExceptionTest.MyFinallyReadLineThrow.readLine(Test.java:10)
at test.ExceptionTest.Test.main(Test.java:18)
Suppressed: java.lang.Exception: close
at test.ExceptionTest.MyFinallyReadLineThrow.close(Test.java:6)
at test.ExceptionTest.Test.main(Test.java:19)
*/
}
}