五、異常 異常概念總結: 練習一:異常的體系 問題: 1. 請描述異常的繼承體系 2. 請描述你對錯誤(Error)的理解 3. 請描述你對異常(Expection的理解) 4. 請描述你對運行時異常(RuntimeException)的理解 答: 1. 異常繼承體係為:異常的根類是 java.la ...
五、異常
異常概念總結:
練習一:異常的體系 問題: 1. 請描述異常的繼承體系 2. 請描述你對錯誤(Error)的理解 3. 請描述你對異常(Expection的理解) 4. 請描述你對運行時異常(RuntimeException)的理解 答: 1. 異常繼承體係為:異常的根類是 java.lang.Throwable,其下有兩個子類: java.lang.Error 與 java.util.Exception 。而Exception又分為編譯時期異常:checked異常,與運行時期異常:runtime異常。 2. Error:表示不可修複的惡性的錯誤,只能通過修改代碼規避錯誤的產生,通常是系統級別的,所以很嚴重。 3. Exception:表示可修複的良性(相對於錯誤)的異常,異常產生後程式員可以並且應該通過代碼的方式糾正,使程式繼續運行,是必須要處理的。 4. 運行時期異常:runtime異常。在運行時期,檢查異常.在編譯時期,運行異常不會編譯器檢測(不報錯)。 練習二:throw與throws的區別 問題: 1. 請描述throw的使用位置,作用是什麼? 2. 請描述throws的使用位置,作用是什麼? 答: 1. throw關鍵字通常用在方法體中,並且拋出一個異常對象。程式在執行到throw語句時立即停止,它後面的語句都不執行。 2. throws關鍵字通常被應用在聲明方法時,用來指定可能拋出的異常。多個異常可以使用逗號隔開。當在主函數中調用該方法時,如果發生異常,就會將異常對象拋給方法調用處。 練習三:異常的處理方式 問題: 1. 異常處理方式有幾種,分別是什麼? 2. 詳細闡述每種方式對異常是如何處理的 答: 1. 異常的處理方式有兩種,分別是使用throws和try...catch...finally 2. throws用在方法的聲明上後接異常類名,是把異常拋給調用者進行處理 3. try...catch...finally是捕獲異常,自己處理,處理完畢後面的程式可以繼續運行 a) try代碼塊中是可能出現異常的代碼 b) catch代碼塊,是遇到異常,對異常進行處理的代碼 c) finally代碼塊是無論是否發生異常,都必須執行的代碼,用於釋放資源. 練習四:常見異常,及產生原因 問題:請列舉常見異常,並說明產生原因。 答: NullPointerException:空指針異常。 當應用試圖在要求使用對象的地方使用了null時,拋出該異常。譬如:調用null對象的實例方法、訪問null對象的屬性、計算null對象的長度等等。 ArrayIndexOutOfBoundsException:數組索引越界異常。 當對數組的索引值為負數或大於等於數組大小時拋出此異常。 ArithmeticException:算術運算異常。 程式中出現了除以零這樣的運算就會出這樣的異常,對這種異常,大家就要好好檢查一下自己程式中涉及到數學運算的地方,公式是不是有不妥了。 NumberFormatException:數字格式異常。 當試圖將一個String轉換為指定的數字類型,而該字元串確不滿足數字類型要求的格式時,拋出該異常。1.異常:
介紹:指的是程式在執行過程中,出現的非正常的情況,最終會導致JVM的非正常停止。 在Java等面向對象的編程語言中,異常本身是一個類,產生異常就是創建異常對象並拋出了一個異常對象。Java處理異常的方式是中斷處理notes:
異常指的並不是語法錯誤,語法錯誤的話 編譯不通過,不會產生位元組碼文件,根本不能運行。①異常體系: API:
異常機制其實就是幫助我們找到程式中的問題, 異常的根類是 java.lang.Throwable,下麵有兩個子類, -java.lang.Error (工程師不能處理,只能儘量避免) -java.util.Exception (由於使用不當導致,可以避免的) 平常所說的異常就是java.util.Exception②Throwable中的常用方法: ⑴列印異常的詳細信息
public void printStackTrace(): 包含了異常的類型,異常的原因,還包括異常出現的位置,在開發和調試階段,都得使用printStackTrace。⑵獲取發生異常的原因
public String getMessage(): 提示給用戶的時候,就提示錯誤原因。⑶獲取異常的類型和異常描述信息(不用)
③異常的分類public String toString():
⑴編譯時期的異常:checked異常.在編譯時期,就會檢查,如果沒有處理異常,則編譯失敗(如日期格式化異常) ⑵運行時期異常:runtime異常.在運行時期,檢查異常,在編譯時期,運行異常不會編譯器檢測(不報錯)(如數學異常)
2.處理異常
五大關鍵字: try catch finally throw throws①拋出異常throw⑴格式:
throw new 異常類名(參數)
⑵拋出異常告訴調用者 :
步驟1:創建一個異常對象.封裝好一些提示信息(信息可以自己編寫) throw new NullPointerException("要訪問的arr數組不存在"); 步驟2:告知調用者,通過throw拋出一個異常對象,傳遞到調用者處,並結束當前方法的執行例子: public static void main(String[] args) {
int[] arr = {2,4,52,2}; int index = 4; int element = getElement(arr, index); System.out.println("element = " + element); System.out.println("over"); }private static int getElement(int[] arr, int index) { // 判斷 索引是否越界 if (index<0||index>arr.length-1){ // 如果越界 當執行完 throw 拋出異常隨心後,方法無法繼續運算 // 這時就會結束當前方法的執行,並將異常 告知 調用者 這時就需要通過異常來解決 throw new ArrayIndexOutOfBoundsException("數組越界"); } int element = arr[index]; return element; } 結果: Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 數組越界l~~~ at DemoThread.ThrowTest.getElement(ThrowTest.java:22) at DemoThread.ThrowTest.main(ThrowTest.java:7) ②Objects非空判斷
還記得我們學習過一個類Objects嗎,曾經提到過它由一些靜態的實用方法組成, 這些方法是null-save(空指針安全的)或null-tolerant(容忍空指針的), 那麼在它的源碼中,對對象為null的值進行了拋出異常操作。 public static <T> T requireNonNull(T obj):查看指定引用對象不是null。public static <T> T requireNonNull(T obj) {
if (obj == null) throw new NullPointerException(); return obj; }③聲明異常throws
說明: 將問題標識出來,報告給調用者,如果方法內通過throw拋出了編譯時異常,而沒有捕獲處理,那麼必須同throws進行聲明 讓調用者去處理. 關鍵字throws運用於方法聲明之上,用於表示當前方法不處理異常,而是提醒該方法的調用者來處理異常 格式: 修飾符 返回值類型 方法名(參數) throws 異常類名1 ,異常類名2...{}例子:
public static void main(String[] args) throws FileNotFoundException { read("a.txt"); } // 如果定義功能時 有問題 發生需要報告給調用者,可以通過在方法上使用throws關鍵字進行聲明 public static void read(String path) throws FileNotFoundException{ if (!path.equals("a.txt")){ // 假設 如果不是a.txt認為 該文件不存在 是一個錯誤 也就是異常 throw throw new FileNotFoundException("文件不存在"); } }④捕獲異常try catch
捕獲異常: Java中對異常有針對性的語句進行捕獲,可以對出現的異常進行指定方式處理格式:
try{
// 編寫可能出現異常的代碼}catch(異常類型 e){處理異常的代碼// 可以是記錄日誌、列印異常信息、繼續拋出異常
} try:該代碼塊中編寫可能產生的異常代碼 catch:用來進行某種異常的捕獲,實現對捕獲到的異常進行處理例子: public static void main(String[] args) { try {
read("a12.txt"); }catch (FileNotFoundException e){ // 列印異常 e.printStackTrace(); } System.out.println("over");} private static void read(String path) throws FileNotFoundException { if (!path.equals("a.txt")){ throw new FileNotFoundException("文件不存在"); } /* if (!path.equals("a.txt")){ throw new IOException(); }*/ } 捕獲的異常常用的方法: Throwable類中定義了一些查看方法: - public String getMessage():獲取異常的描述信息,原因(提示給用戶的時候,就提示錯誤原因。 - public String toString():獲取異常的類型和異常描述信息(不用)。 - public void printStackTrace():列印異常的跟蹤棧信息並輸出到控制台。 包含了異常的類型,異常的原因,還包括異常出現的位置,在開發和調試階段,都得使用printStackTrace。 在開發中呢也可以在catch將編譯期異常轉換成運行期異常處理。 多個異常使用捕獲又該如何處理呢? 1. 多個異常分別處理。 2. 多個異常一次捕獲,多次處理。 3. 多個異常一次捕獲一次處理。 一般我們是使用一次捕獲多次處理方式, 格式如下: try{ 編寫可能會出現異常的代碼 }catch(異常類型A e){ 當try中出現A類型異常,就用該catch來捕獲. 處理異常的代碼 //記錄日誌/列印異常信息/繼續拋出異常 }catch(異常類型B e){ 當try中出現B類型異常,就用該catch來捕獲. 處理異常的代碼 //記錄日誌/列印異常信息/繼續拋出異常 } notes: 註意:這種異常處理方式,要求多個catch中的異常不能相同, 並且若catch中的多個異常之間有子父類異常的關係, 那麼子類異常要求在上面的catch處理, 父類異常在下麵的catch處理 ⑤finally代碼塊 說明: 有一些特定的代碼無論異常是否發生,都需要執行。另外,因為異常會引發程式跳轉,導致有些語句執行不到。 而finally就是解決這個問題的,在finally代碼塊中存放的代碼都是一定會被執行的。 打開一些物理資源(比如磁碟文件/網路鏈接/資料庫鏈接等)我們都得在使用完之後,最終關閉打開的資源 用法: try catch finally:自身需要處理異常,最終還得關閉資源。 notes: finally不能單獨使用。 例子: public static void main(String[] args) { try { read("a11.txt"); }catch (FileNotFoundException e){ e.printStackTrace(); }finally { System.out.println("不管怎麼樣我都要執行"); } System.out.println("over"); } private static void read(String path) throws FileNotFoundException { if (!path.equals("a.txt")){ throw new FileNotFoundException("文件不存在!"); } } tips: 只有在try或者catch中調用退出JVM的相關方法時,此時finally才不會執行,否則finally用遠會執行 結果: 不管怎麼樣我都要執行 java.io.FileNotFoundException: 文件不存在! over at DemoThread.finallyTest01.read(finallyTest01.java:19) at DemoThread.finallyTest01.main(finallyTest01.java:8) ⑥異常註意事項 ⑴運行時期異常被 拋出可以不處理,既不捕獲也不聲明拋出 ⑵如果父類拋出多個異常,子類覆蓋父類方法時,只能拋出相同的異常或者他的子集 ⑶父類方法沒有拋出異常,子類覆蓋父類該方法時也不可拋出異常,此時子類產生該異常,只能捕獲處理,不能聲明拋出 ⑷當多異常處理時,捕獲處理,前邊的類不能時後邊類的父類 ⑸當try/catch後可以主機finally代碼塊,其中的代碼一定會被執行,通常用於資源回收 ⑹如果finally有return語句,永遠返回finally中的結果,避免該情況
3.自定義異常
說明: 為什麼需要自定義異常類: Java中不同的異常類,分別表示著某一種具體的異常情況,那麼在開發中總是有些異常情況是SUN沒有定義好的,此時我們根據自己業務的異常情況來定義異常類。,例如年齡負數問題,考試成績負數問題。 在上述代碼中,發現這些異常都是JDK內部定義好的,但是實際開發中也會出現很多異常,這些異常很可能在JDK中沒有定義過,例如年齡負數問題,考試成績負數問題.那麼能不能自己定義異常呢? 什麼是自定義異常類: 在開發中根據自己業務的異常情況來定義異常類. 自定義一個業務邏輯異常: LoginException。一個登陸異常類。 異常類如何定義: 1. 自定義一個編譯期異常: 自定義類 並繼承於java.lang.Exception。 2. 自定義一個運行時期的異常類:自定義類 並繼承於java.lang.RuntimeException 例子: public class DiyETest { private static String[] names= {"bill","hill","jill"}; public static void main(String[] args) { // 模擬登錄 try{ // 可能出現異常的代碼 checkUsername("bill"); // 如果沒有就是註冊成功 System.out.println("註冊成功"); }catch (LoginException e){ e.printStackTrace(); } } private static boolean checkUsername(String uname) throws LoginException { for (String name:names){ if (name.equals(uname)){ // 如果名字在其中 則拋出 登錄異常 throw new LoginException("禁止登錄"); } } return true; } } class LoginException extends Exception{ public LoginException() { } /** * * @param name 表示異常提示 */ public LoginException(String name){ super(name); } }<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">