轉載請保留原文鏈接: http://dashidan.com/article/java/basic/16.html
16.Java異常
Java異常是Java提供的一種識別及響應錯誤的一致性機制.
① Java異常機制相關關鍵字
Java異常機制相關關鍵字有: try
、catch
、finally
、throw
、throws
. 關鍵字解釋:
try 用於監聽. 將被監聽的代碼(可能拋出異常的代碼)放在try語句塊之內, 當try語句塊內發生異常時,異常就被拋出.
catch 用來捕獲try語句塊中發生的異常.
finally finally語句塊總是會被執行. 主要用於回收在
try
塊裏打開的物理資源(如文件, 網絡連接, 數據庫連接等).
finally語句中return
只有finally塊執行完成之後,纔會執行try或者catch塊中的return或者throw語句. 如果finally中使用了return或者throw等終止方法的語句,則就不會跳回執行,直接停止.
throw 用於拋出異常.
throws 用在方法簽名中,用於聲明該方法可能拋出的異常.
② Java異常框架
Java將可拋出(Throwable)的結構分爲三種類型:
編譯異常(Checked Exception)
運行時異常(RuntimeException)
錯誤(Error)
Java異常框架繼承關係如圖:
1.Throwable
Throwable
是Java
語言中所有錯誤或異常的超類, 包含兩個子類:Error
和Exception
.它們通常用於指示發生了異常情況.Throwable
包含了其線程創建時線程執行堆棧的快照,提供了printStackTrace()
等接口用於獲取堆棧跟蹤數據等信息.
2.運行時異常RuntimeException
RuntimeException
是那些可能在Java
虛擬機正常運行期間拋出的異常的超類, 簡稱運行時異常
. RuntimeException及其子類都被稱爲運行時異常.
Java編譯器不會檢查運行時異常.當程序中可能出現這類異常時,倘若既"沒有通過throws聲明拋出它",也"沒有用try-catch語句捕獲它",還是會編譯通過.
雖然Java編譯器不會檢查運行時異常, 但是我們也可以通過throws進行聲明拋出, 也可以通過try-catch對它進行捕獲處理. 如果產生運行時異常,則需要通過修改代碼來進行避免.
例如:
除數爲零時產生的ArithmeticException異常
數組越界時產生的IndexOutOfBoundsException異常
fail-fail機制產生的ConcurrentModificationException異常等,都屬於運行時異常.
異常 | 描述 |
ArithmeticException | 除數爲零異常 |
ArrayIndexOutOfBoundsException | 數組越界 |
ClassCastException | 對象轉型錯誤 |
IllegalArgumentException | 參數不合法 |
IndexOutOfBoundsException | 指示某排序索引(例如對數組、字符串或向量的排序)超出範圍 |
NegativeArraySizeException | 數組長度爲負值 |
NullPointerException | 空指針異常 |
NumberFormatException | 當應用程序試圖將字符串轉換成一種數值類型,但該字符串不能轉換爲適當格式時,拋出該異常. |
3.編譯異常Exception
Exception
類以及Exception
的子類中除了"運行時異常"之外的其它子類都屬於被檢查異常. 此類異常,要麼通過throws進行聲明拋出,要麼通過try-catch進行捕獲處理,否則不能通過編譯.
異常 | 描述 |
ClassNotFoundException | 應用程序試圖加載類時,找不到相應的類,拋出該異常. |
FileNotFoundException | 文件不存在異常 |
ClassCastException | 對象轉型錯誤 |
InterruptedException | 一個線程被另一個線程中斷,拋出該異常. |
NoSuchFieldException | 請求的變量不存在 |
NoSuchMethodException | 請求的方法不存在 |
4.Error
Error
類及其子類統稱錯誤
. 用於指示試圖捕獲的嚴重問題, 大多數這樣的錯誤都是異常條件. 和運行時異常
一樣, 編譯器也不會檢查Error
. 當資源不足、約束失敗、或是其它導致程序無法繼續運行的條件發生時, 就產生錯誤. 程序本身無法修復這些錯誤.
例:
VirtualMachineError就屬於錯誤.
按照Java慣例, 不應該實現任何新的Error子類, 需要自定義異常可以採用Exception類.
到底該哪一種異常?
對於可以恢復的條件使用被檢查異常,對於程序錯誤使用運行時異常.虛擬機及系統錯誤採用Error.
③ 捕獲異常
使用try
和catch
關鍵字可以捕獲異常.try/catch
代碼塊放在異常可能發生的地方.
語法如下:
try { /** 程序代碼*/} catch (Exception e) { /** 異常處理*/}
一個try
代碼塊後面跟隨多個catch
代碼塊的情況就叫多重捕獲. 可以在 try 語句後面添加任意數量的 catch 塊. 如果保護代碼中發生異常,異常被拋給第一個 catch 塊. 如果拋出異常的數據類型與捕獲異常類型匹配, 就會被捕獲. 如果不匹配,它會被傳遞給下一個catch
塊.直到異常被捕獲或者通過所有的catch
塊.
語法如下:
try { /** 程序代碼*/} catch (Exception1 e) { /** 異常處理*/} catch (Exception1 e) { /** 異常處理*/}
④ 拋出異常
可以使用throw
關鍵字拋出一個異常.
public static void testThrow() { /** 方法體*/ throw new NullPointerException();}
如果一個方法沒有捕獲一個編譯異常
, 那麼該方法必須使用throws
關鍵字來聲明. throws
關鍵字放在方法簽名的尾部.
示例代碼:
public static void testThrows() throws NullPointerException { /** 方法體*/}
一個方法可以聲明拋出多個異常,多個異常之間用逗號隔開.
例如,下面的方法聲明拋出NullPointerException
和ArithmeticException
示例代碼:
public static void testThrows() throws NullPointerException, ArithmeticException { /** 方法體*/}
⑤ finally關鍵字
finally
關鍵字用來創建在try
代碼塊後面執行的代碼塊. 無論是否發生異常,finally
代碼塊中的代碼總會被執行. 在finally
代碼塊中,可以運關閉鏈接, 釋放系統資源等必須要執行的語句.
finally
代碼塊出現在catch
代碼塊最後.
語法如下:
try { /** 方法體*/} catch (Exception e) { /** 異常處理*/} finally { /** finally語句*/}
finally 塊並非強制添加.
try 代碼後不能既沒 catch 塊也沒 finally 塊.
示例代碼:
package com.dashidan.lesson15;/** * 大屎蛋教程網-dashidan.com * <p> * Java教程基礎篇: 15.Java異常 * 測試finally return */public class Demo2 { public static void main(String[] args) { int result = testFinallyReturn(); System.out.println("result: " + result); } public static int testFinallyReturn() { int a; try { a = 1; /** 拋出異常*/ System.out.println("拋出異常"); throw new NullPointerException(); } catch (NullPointerException e) { a = 2; /** 捕獲異常*/ System.out.println("捕獲異常"); e.printStackTrace(); /** 注意這裏沒有返回*/ System.out.println("注意這裏沒有返回"); return a; } finally { a = 3; System.out.println("finally執行返回"); /** 拋出異常後, 執行finally的語句, 如果這裏返回,不再執行catch中語句*/ return a; } }}
輸出:
拋出異常 捕獲異常 注意這裏沒有返回 finally執行返回 result: 3 java.lang.NullPointerException at com.dashidan.lesson15.Demo2.testFinallyReturn(Demo2.java:21) at com.dashidan.lesson15.Demo2.main(Demo2.java:11) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144)
⑥ 自定義異常
在Java
中自定義異常需要注意:
所有異常都必須是 Throwable 的子類.
如果想寫一個檢查性異常類,則需要繼承 Exception 類.
如果想寫一個運行時異常類,那麼需要繼承 RuntimeException 類.
package com.dashidan.lesson15;/** * 大屎蛋教程網-dashidan.com * <p> * Java教程基礎篇: 15.Java異常 * 自定義異常 */public class SelfException extends Exception {}
示例代碼:
package com.dashidan.lesson15;/** * 大屎蛋教程網-dashidan.com * <p> * Java教程基礎篇: 15.Java異常 */public class Demo1 { public static void main(String[] args) { try { /** 方法體*/ testThrow(); testThrows(); } catch (NullPointerException e) { /** 異常處理*/ System.out.println("run catch NullPointerException."); e.printStackTrace(); } catch (Exception e) { /** 異常處理*/ System.out.println("run catch Exception."); e.printStackTrace(); } finally { /** finally語句*/ System.out.println("run finally."); } } public static void testThrow() { /** 方法體*/ throw new NullPointerException(); } public static void testThrows() throws NullPointerException, ArithmeticException { /** 方法體*/ }}
輸出:
java.lang.NullPointerException at com.dashidan.lesson15.Demo1.testThrow(Demo1.java:30) at com.dashidan.lesson15.Demo1.main(Demo1.java:12) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:144) run catch NullPointerException. run finally.
⑦ 相關文章