一、什麼是異常
異常(Exception)指程式執行中出現的不期而至的各種狀況,如:
- 檔案找不到
- 網路連線失敗
- 非法引數等
注意:異常發生在程式執行期間,它影響了正常的程式執行流程
二、異常的簡單分類:
- 檢查性異常:最具代表性的異常
- 使用者錯誤或者問題引起的異常,這是程式設計師無法預見的異常,這些異常在編譯時不能被簡單地忽略
- 例如:開啟一個不存在的檔案時,一個異常就發生了
- 執行時異常:可能會被程式設計師避免的異常
- 與檢查性異常相反,執行時異常可能在編譯時被忽略
- 錯誤ERROR:錯誤不是異常,而是脫離程式設計師控制的問題
- 錯誤在程式碼中通常被忽略
- 例如:當一個棧溢位時,一個錯誤就發生了,它們在編譯時也檢查不到
三、異常體系結構
Java把異常當作物件來處理,並定義了一個基類java.lang.Throwable作為所有異常的超類
在java中 API中已經定義了許多異常類,這些異常類分為兩大類:Error(錯誤)和Exception(異常)
1、Exception
在Exception分支中有一個重要的子類RuntimeException(執行時異常),包括以下異常:
- ArrayIndexOutOfBoundsException(陣列下標越界異常)
- NullPointerException(空指標異常)
- ArithmeticException(算術異常)
- MissingResourceException(丟失資料)
- ClassNotFoundException(找不到類)
- UnKnownTypeException(未知型別異常)
- IllegalArgumentException(非法引數異常)
注意:這些異常一般是由程式邏輯錯誤引起的,程式應該從邏輯角度儘可能避免這類異常的發生
2、Error
- Error類物件由Java虛擬機器生成並丟擲,大多數錯誤與程式碼編寫者所執行的操作無關
- Java虛擬機器執行錯誤(Virtual MachineError),當JVM不再有繼續執行操作所需的記憶體資源時,將出現OutOfMemoryError;這些異常出現時,Java虛擬機器(JVM)一般會選擇執行緒終止
- 發生在虛擬機器試圖執行應用時,如類定義錯誤(NotClassDefFoundError)、連結錯誤(LinkageError)
- 這些錯誤是不可查的,因為它們在應用程式的控制和處理能力之外,而且絕大多數是程式執行時不允許出現的狀況
3、Error和Exception的區別:
- Error通常是災難性的致命的錯誤,是程式無法控制和處理的,當出現這些異常時,Java(JVM)一般會選擇終止執行緒
- Exception通常情況下是可以被程式處理的,並且在程式中應該儘可能去處理這些異常
四、異常捕獲
關鍵字:try...catch...finally
執行以下程式碼會報錯:ArithmeticException: / by zero
- 是Java中的一個執行時異常類,它繼承自java.long.RuntimeException類
- 該異常表示在數學運算中發生了算術錯誤或不合法的操作。
//異常捕獲
public class Exception {
public static void main(String[] args) {
int a = 5;
int b = 0;
System.out.println(a/b);
}
}
處理異常的方法:
public class CatchException {
public static void main(String[] args) {
int a = 5;
int b = 0;
//異常捕獲
//可以自己寫,也可以使用快捷鍵Ctrl+Alt+T(先選中需要捕抓的語句)
try { //監控區域
System.out.println(a/b);
} catch (Exception e) { //catch(捕獲的異常型別) 捕獲異常
//e.printStackTrace();//列印錯誤的棧資訊
System.out.println("0不能作為除數");
} finally { //處理善後工作,無論有沒有異常都會執行(可有可無)
System.out.println("finally");
}
}
}
1、多層捕獲
注意:多次捕獲異常時,需要按從低到高的異常階級來,可參考異常體系結構圖
public class CatchException_mul {
public static void main(String[] args) {
int a = 5;
int b = 0;
try {
System.out.println(a/b);
} catch (Error e) {
System.out.println("Error");
} catch (Exception e){
System.out.println("Exception");//異常匹配成功,輸出
}catch (Throwable t){
System.out.println("Throwable");//Throwable最高階的異常
}finally {
System.out.println("finally");
}
}
}
執行結果如下:
2、主動丟擲異常
關鍵字:throw,throws
public class throw01 {
public static void main(String[] args) {
new throw01().test(5,0);
}
//自定義方法,丟擲異常
public void test (int x,int y){
if(y == 0){
throw new ArithmeticException();//主動丟擲異常,一般在方法中使用
}
}
}
五、自定義異常(不常用)
使用Java內建的異常類可以描述在程式設計時出現的大部分異常情況;除此之外,使用者還可以自定義異常
注意:使用者自定義異常類,需要繼承Exception類
1、定義步驟
- 建立自定義異常類
- 在方法中透過throw關鍵字丟擲異常
- 如果在當前丟擲異常的方法中處理異常,可以使用try-catch語句捕獲並處理;否則在方法的宣告處透過throws關鍵字指明要拋處給方法呼叫者的異常
- 在出現異常方法的呼叫者中捕獲並處理異常
//自定義的異常類
//繼承Exception類
public class D_Exception extends Exception {
//傳遞資料 > 10
private int derail;
//方法
public D_Exception(int x){
this.derail = x;
}
//toString:異常的列印資訊
@Override //重寫toString()方法
public String toString() {
//內容自定義
return "D_Exception{"+ derail+"}";
}
}
//測試類
public class Application {
//可能存在異常的方法
//如果這裡不加throws...,則需要使用try..catch捕獲
static void test(int x) throws D_Exception {
System.out.println("傳遞的引數是:"+ x);
if(x>10){
throw new D_Exception(x);//丟擲異常
}
System.out.println("OK");
}
//main方法
public static void main(String[] args) {
//捕獲異常
try {
test(11);//11>10,輸出異常!!!
} catch (D_Exception e) {
//e:D_Exception中定義的異常資訊
System.out.println("D_Exception=>"+e);//處理異常
}
}
}
2、經驗總結
- 處理執行時異常時,採用邏輯去合理規避同時用try-catch輔助處理
- 在多重catch塊後面,可以加一個catch(Exception) 來處理可能會被遺漏的異常
- 對於不確定的程式碼,也可以加上try-catch,處理潛在的異常
- 儘量去處理異常,切忌只是簡單地呼叫printStackTrace()去列印輸出
- 具體如何處理異常,要根據不同的業務需求和異常型別去決定
- 儘量新增finally語句塊去釋放佔用的資源(IO、Scanner.....)