------Java培訓、Android培訓、iOS培訓、.Net培訓、期待與您交流! -------
異常
異常就是Java程序在運行過程中出現的導致程序無法正常運行的錯誤。
Java 中異常繼承體系,頂層的類
java.lang.Throwable
java.lang.Exception 所有異常的超類
RuntimeException 運行時異常可以不處理
非RuntimeExceptioin非運行時異常必須捕獲處理
java.lang.Error 所有錯誤的超類
異常處理機制
當程序中拋出一個異常後,程序從程序中導致異常的代碼處跳出,java虛擬機檢測尋找和 try關鍵字匹配的處理該異常的 catch塊,如果找到,將控制權交到 catch塊中的代碼,然後繼續往下執行程序,try 塊中發生異常的代碼不會被重新執行。如果沒有找到處理該異常的 catch 塊,在所有的 finally 塊代碼被執行和當前線程所屬的ThreadGroup 的 uncaughtException 方法被調用後,遇到異常的當前線程被中止。
異常處理
在Java語言中,使用 throw 關鍵字來引發異常。
對異常處理的兩條途徑爲:
1. 使用 throws 拋出異常
2. 使用 try-catch 語句捕獲異常
n try-catch
try {
可能出現異常的代碼
} catch(Exception e) {
異常處理代碼
}
多個 catch
每個 try 語句塊可以伴隨一個或多個 catch 語句,用於處理可能產生的不同類型的異常。catch 捕獲的異常類型由上至下的捕獲異常類型的順序應是子類到父類的。子類型異常在前,父類型異常在後,這樣的順序依次捕獲。否則編譯不通過。
finally 語句
爲異常處理提供一個統一的出口,使得在控制流程跳轉到程序其它部分以前,能夠對序的狀態作統一管理。無論 try 所指定的程序塊中是否拋出異常,finally 所指定的代碼都要被執行。通常在finally 語句中可以進行資源的釋放工作。
throw 關鍵字
寫在方法內部,拋出異常,後面寫 new 異常對象
當程序發生錯誤而無法處理的時候,會拋出對應的異常對象,或用於自行拋出異常。
throws 關鍵字
寫在方法聲明上,告訴調用者處理異常,後面寫異常類類名
方法中可能會因某些錯誤而引發異常,希望調用者處理,聲明方法會拋出異常。
method()throws Exception { // 聲明異常,讓調用者處理
throw new Exception() // 拋出異常
}
重寫方法時的throws
如果使用繼承時,在父類的某個方法上聲明 throws 某些異常,而在子類中重新定義該方法時,
可以:
不處理異常(重新定義時不設定throws)
可僅 throws 父類中聲明的部分異常
可 throws 父類方法中拋出異常的子類異常
不可以:
throws 出額外的異常
throws 父類方法中拋出異常的父類異常
概括爲:父類方法中拋出異常,子類重寫可拋可不拋;父類不拋,子類不能拋出。
異常的分類
——運行時異常RuntimeException ,又稱非檢測異常
直接或間接繼承RuntimeException 的異常。不受編譯器檢查與處理或聲明規則的限制,在發生此類異常時,不一定非要採取處理操作,編譯器不會檢查是否解決異常。
——非運行時異常又稱可檢測異常,編譯時異常
是指除了RuntimeException 以外的其他異常,是程序有邏輯錯誤。可檢測異常經編譯器驗證,對於聲明拋出異常的任何方法,編譯器將強制執行處理或聲明規則,不捕捉這個異常,編譯器就通不過,不允許編譯。
Java編譯器要求方法必須聲明拋出可能發生的非運行時異常,但是不要求必須聲明拋出未被捕獲的運行時異常。
——常見的運行時異常:
IllegalArgumentException 不合法參數異常:向方法傳遞一個不合法或不正確參數
NullPointerException空指針異常:當操作一個空引用時會出現此異常
NumberFormatException 數字格式化異常:試圖將字符串轉換成一種數值類型,但該字符串不能轉換爲適當格式時,拋出該異常
ClassCastException 類型轉換異常:強制類型轉換類型不匹配時出現此異常
ArrayIndexOutOfBoundsException 數組下標越界異常:當使用一個不存在的數組下標時出現此異常。
ArithmeticException 數學異常:當出現異常的運算條件時出現此異常
——常見的非運行時異常:
SQLException 提供關於數據庫訪問錯的異常
IOException 當發生某種 I/O 異常時,拋出此異常
ClassNotFoundException 當應用程序試圖使用 Class 類中的 forName 方法、loadClass 方法時,拋出該異常
Throwable 中的方法
getMessage() // 獲取異常信息,返回字符串
toString() // 獲取異常類名和異常信息,返回字符串
printStackTrace() // 獲取異常類名和異常信息及出現的位置,輸出執行堆棧信息
printStackTrace(PrintStream s) // 將異常內容保存在日誌文件中
自定義異常
爲了更加精準地捕獲和處理異常以呈現更好的用戶體驗,需要開發者自定義異常。
繼承 Exception 自定義異常,定義好自定義異常後,可以通過IDE生成相應構造方法。
class 自定義異常類名 extendsException {
…
}
編譯時期異常和運行時期異常的區別:
編譯時期異常:拋出的異常類,不是RuntimeException類或者其子類
調用者,調用一個拋出異常的方法,如果不處理,編譯失敗
異常是編譯器最後檢測的問題
運行時期異常:拋出的異常類,是RuntimeException類和其子類
拋出的是運行時期異常,凡是方法內部拋出的異常是運行時期,方法的聲明上,無需throws,對應方法的調用者,就不需要處理異常。
運行時期異常的設計思想:
運行時期異常,在程序的運行中,是不能發生的,如果真的發生了,請程序人員停止程序,修改源代碼,運行時期異常一旦發生,後面的代碼就沒有運行的必要了。
finally 的特點及作用
特點:被 finally 控制的語句體一定會執行,在return 返回值之前執行
特殊情況:在執行finally之前jvm 退出(如System.exit(0)),線程死亡,關閉CPU
作用:釋放資源(I/O 操作和數據庫操作)
packagecn.itcast;
/*
* finally 語句塊不應該出現應該出現return
* return ret 最好是其他語句來處理相關邏輯
*
* 正確運行結果是:
* i= 2
* i= 1
* testEx2, catch exception
* testEx2, finally; return value = false
* testEx1, finally; return value = false
* testEx, finally; return value = false
*/
publicclass TestException {
public TestException() {
}
boolean testEx() throws Exception {
booleanret = true;
try {
ret = textEx1(); // 接收返回值false
} catch (Exception e) {
System.out.println("testEx,cathch exception");
ret = false;
throwe;
} finally {
System.out.println("testEx,finally; return value= " + ret); //false
returnret; // false
}
}
boolean textEx1() throws Exception {
booleanret = true;
try {
ret = textEx2(); // 接收返回值false
if (!ret) {
returnfalse;
}
System.out.println("testEx1,at the end of try");
returnret;
} catch (Exception e) {
System.out.println("testEx1,cathch exception");
ret = false;
throwe;
} finally {
System.out.println("testEx1,finally; return value= " + ret); //false
returnret; // try塊中已有返回值,此爲無效語句
}
}
boolean textEx2() throws Exception {
booleanret = true;
try {
intb = 12;
intc;
for (inti = 2; i>= -2; i--) {
c= b / i;
System.out.println("i=" + i);// 2, 1
}
returntrue; // 上面發生異常,此句未執行
} catch (Exception e) {
System.out.println("testEx2,catch exception");
ret = false;
throwe;
} finally {
System.out.println("testEx2,finally; return value= " + ret); //catch語句中賦值false
returnret; // false
}
}
publicstaticvoid main(String[] args) {
TestExceptiontestException1 = newTestException();
try {
testException1.testEx();
// System.out.println(testException1.testEx());// false
} catch (Exception e) {
e.printStackTrace();
}
}
}