Java異常捕獲與處理
文章目錄
1 異常(Exception)
異常是程序中的一些錯誤,但並不是所有的錯誤都是異常,並且錯誤有時候是可以避免的。異常發生的原因有很多,例如:用戶輸入了非法數據、要打開的文件不存在、網絡通信時連接中斷或者JVM內存溢出等。菜鳥教程
2 異常分類
- 檢查性異常:最具代表的檢查性異常是用戶錯誤或問題引起的異常,這是程序員無法預見的。
- 運行時異常:運行時異常是可能被程序員避免的異常。與檢查性異常相反,運行時異常可以在編譯時被忽略。
- 錯誤ERROR:錯誤不是異常,而是脫離程序員控制的問題。錯誤在代碼中通常被忽略。例如,當棧溢出時,一個錯誤就發生了,它們在編譯也檢查不到的。
3 異常體系結構
Java把異常當作對象來處理,並定義了一個基類java.lang.Throwable作爲所有異常的超類。異常類分類兩大類:錯誤(Error)和異常(Exception)
3.1 錯誤(Error)
- Error類對象由Java虛擬機生成並拋出,大多數錯誤與代碼編寫者所執行的操作無關。
- Java虛擬機運行錯誤(Virtual MachineError),當JVM不再有繼續執行操作所需的內存資源時(溢出),將出現OutMemoryError。這些異常發生時,JVM一般會選擇線程終止。
- 虛擬機試圖執行應用時的錯誤,如類定義錯誤(NoClassDefFoundError)、鏈接錯誤(LinkageError)。這些錯誤是不可查的,因爲它們在應用程序的控制和處理能力之外,而且絕大多數是程序運行時不允許出現的狀況。
3.2 運行時異常(RuntimeException)
名稱 | 描述 |
---|---|
ArrayIndexOutOfBoundsException | 數組下標越界 |
NullPointerException | 空指針異常 |
ArithmeticException | 算術異常 |
MissingResourceException | 丟失資源 |
ClassNotFoundException | 找不到類異常 |
… | … |
這些異常一般由程序邏輯錯誤引起的,是不檢查異常,程序中可以選擇捕獲處理,也可以不處理。
Error和Exception的區別:Error通常是災難性的致命的錯誤,是程序無法控制和處理的,當出現這些異常時,JVM一般會選擇終止線程,Exception通常情況下是可以被程序處理的,並且在程序中應該儘可能的去處理這些異常。
4 異常處理機制
異常處理的五個關鍵字:try
、catch
、finally
、throw
、throws
。
4.1 捕獲異常
public static void main(String[] args) {
int a = 1;
int b = 0;
try {//監控區域
System.out.println(a / b);
} catch (ArithmeticException e) {//catch(想要捕獲的異常類) 捕獲異常
System.out.println("程序出現異常,變量b不能爲0");
} finally {//處理善後,例如關閉IO流,資源等
System.out.println("finally");
}
}
運行結果:
程序出現異常,變量b不能爲0
finally
try
區域是監控區域,用於需要異常處理的代碼塊。catch
區域是異常捕獲區域,參數爲需要捕捉的異常類型,可以進行相關的異常處理。finally
區域是最終處理區域,無論try
區域內部的代碼是否存在異常都會執行,一般用於釋放資源。try
和catch
兩個區域必須存在,finally
區域可有可無,根據實際情況判斷。
4.2 拋出異常
public static void main(String[] args) {
int a = 1;
int b = 0;
try {
if (b == 0) {//主動拋出異常
throw new ArithmeticException();
}
System.out.println(a / b);
} catch (Exception e) {
System.out.println("exception");
e.printStackTrace();//打印錯誤的棧信息
}
}
運行結果:
exception
java.lang.ArithmeticException
at com.base.J_ErrorException.Demo2.main(Demo2.java:10)
- 當我們知道程序會存在某種異常時,可以使用
throw
關鍵字在方法內部拋出異常。 - 可以使用
printStackTrace()
方法在控制檯打印異常捕獲信息
public static void main(String[] args) {
try {
new Demo3().test(1, 0);
}catch (ArithmeticException e){
System.out.println("捕捉到異常");
e.printStackTrace();
}
}
public void test(int a, int b) throws ArithmeticException{
System.out.println(a / b);
}
throws
關鍵字用於聲明方法可能存在的異常,使用者調用該方法時,應作對應的異常捕獲處理。
5 自定義異常
使用Java內置的異常類可以描述在編程時出現的大部分異常情況,除此之外,用戶可以自定義異常類,只需要繼承Exception類即可。
/**
* 傳遞值不能大於10的自定義異常類
*/
public class MyException extends Exception{
private int detail;
public MyException(int a) {
this.detail = a;
}
@Override
public String toString() {//異常的打印信息
return "MyException{" +
"detail=" + detail +
'}';
}
}
//測試
class Test{
static void test(int a) throws MyException {
System.out.println("傳出的參數爲:" + a);
if (a >10){
throw new MyException(a);//拋出異常
}
System.out.println("ok");
}
public static void main(String[] args) {
try{
test(11);
}catch (MyException e){
System.out.println(e);
}
}
}
運行結果:
傳出的參數爲:11
MyException{detail=11}
at com.base.J_ErrorException.Test.test(MyException.java:27)
at com.base.J_ErrorException.Test.main(MyException.java:34)
編寫步驟:
- 創建自定義異常
- 在方法中通過throw關鍵字拋出異常對象
- 如果在當前拋出的異常方法中處理異常,可以使用try-catch語句捕獲並處理異常;否則在方法的聲明出通過throws關鍵字指明要拋出給方法調用者的異常,繼續進行下一步操作。
- 在出現異常方法的調用者中捕獲並處理異常。
6 總結
- 處理運行時異常時,採用邏輯去合理規避同時輔助try-catch處理。
- 在多重catch塊後面,可以加一個catch(Exception)來處理可能會被遺漏的異常。
- 對於不確定的代碼,也可以加上try-catch,處理潛在的異常。
- 儘量去處理異常,切忌只是簡單地調用printStackTrace()去打印輸出
- 具體如何處理異常,要根據不同的業務需求和異常類型去決定
- 儘量添加finally語句塊去釋放佔用的資源。
時間:2020年7月3日17:15:21