異常的簡單分類 檢查性異常:最具代表性的檢查性異常是用戶錯誤或問題引起的異常,這是程式員無法預見的。例如用戶要打開一個不存在的文件,一個異常就發生了,這些異常在編譯時不能被簡單的忽略。 運行時異常:運行時異常是可能被程式員避免的異常,與檢查性異常相反,運行時異常可以在編譯時被忽略。 錯誤(error ...
異常的簡單分類
- 檢查性異常:最具代表性的檢查性異常是用戶錯誤或問題引起的異常,這是程式員無法預見的。例如用戶要打開一個不存在的文件,一個異常就發生了,這些異常在編譯時不能被簡單的忽略。
- 運行時異常:運行時異常是可能被程式員避免的異常,與檢查性異常相反,運行時異常可以在編譯時被忽略。
- 錯誤(error):錯誤不是異常,而是脫離程式員控制的問題。錯誤在代碼中通常被忽略。例如,當棧溢出時,一個錯誤就發生了,它們在編譯時也檢查不到。
Excetpion
在Exception分支中,有一個重要的子類:RuntimeException(運行時異常),包括:
- ArithmeticException,算術異常
- MissingResourceException,丟失資源異常
- ClassNotFoundException,找不到類
- NullPointerException,空指針異常
- IllegalArgumentException,非法參數異常
- ArrayIndexOutOfBoundsException,數組下表越界異常等
這些異常時不檢查異常,程式中可以選擇捕獲處理,也可以選擇不處理,這些異常一般是由程式員邏輯錯誤引起,程式應該從邏輯角度儘可能避免這類異常的發生。
異常處理機制
異常處理一般有捕獲異常和拋出異常兩個過程,相關關鍵字有以下五個:try、catch、finally、throw、throws
int a = 1;
int b = 0;
try { //try里的是監控區域
System.out.println(a / b);
} catch (Error e) { //catch(想要捕獲的異常類型),最高是throwable
System.out.println("Error");
} catch (Exception e) { //可以捕獲多個異常,從上到下,異常的範圍要逐漸擴大,或者不相交
System.out.println("Exception");
} catch (Throwable t) { //異常的最高類別是Throwable
System.out.println("Throwable");
} finally { //處理善後工作
//finally不是必要的,但在某些場景,比如處理I/O流,需要關閉資源時,需要用來善後
System.out.println("finally");
}
throw和throws
throw用來主動拋出異常,throws則是在方法定義中拋出異常:
public class Test{
public static void main(String[] args){
int a = 1;
int b = 0;
new Test().test(a, b);
}
//使用throws在方法上拋出異常
public void test(int a, int b) throws ArithmeticException {
if (b == 0) {//throw throws
throw new ArithmeticException();//主動拋出異常,一般在方法中使用。假設這方法中處理不了這個異常,就在方法上拋出異常
}
System.out.println(a / b);
}
Error和Exception的區別:Error通常是災難性的致命錯誤,是程式無法控制和處理的,當出現這些異常時,Java虛擬機一般會選擇終止線程;Exception通常情況下是可以被程式處理的,並且在程式中應該儘可能地去處理這些異常。
自定義異常
Java內置的異常類可以描述在編程時出現的大部分異常情況。除此之外,用戶還可以自定義異常。用戶自定義異常類,只需要繼承Exception類即可,大致分為以下幾個步驟
- 創建自定義異常類
- 在方法中通過throw關鍵字拋出異常對象
- 如果在當前拋出的方法中處理異常,可以使用try-catch語句捕獲並處理;否則在方法的聲明處通過throws關鍵字指明要拋出給方法調用者的異常,繼續進行下一步操作。
- 在出現異常的方法的調用者中捕獲並處理異常。
//通過繼承Exception類,自定義異常
public class MyException extends Exception {
//用來檢查數字輸入異常
private int detail;
public MyException(int a) {
this.detail = a;
}
@Override
public String toString() {
return "MyException{" + detail + '}';
}
}
//測試:
public class Test {
//將a>10定義為異常情況,並拋出自定義異常
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.test(115);
} catch (MyException e) { //捕獲自定義異常,並列印信息
System.out.println("MyException=>" + e);
}
}
}
自定義異常情況為:
實際應用中的經驗總結
- 處理運行時異常時,採用合適的邏輯去合理規避異常情況,同時使用try-catch輔助處理
- 在多種catch塊後面,可以加一個catch(Exception)來處理可能會被遺漏的異常
- 對於不確定的代碼,也可以加上try-catch,處理潛在的異常
- 儘量去處理異常,切忌只是簡單的調用printStackTrace()去列印輸出
- 具體如何處理異常,要根據不同的業務需求和異常類型去決定
- 儘量添加finally語句塊去釋放占用的資源,比在I/O流、Scanner場景中