標籤:
異常允許我們強制停止程式運行,並告訴我們出現了什麼問題,或者強製程序去處理問題,並返回到穩定點。
Java提供一個Throwable類,該類是所有異常和錯誤類的超類。只有當對象是此類的執行個體時,才能通過Java虛擬機器或者Java的throw語句拋出。throwable類及其子類的結構圖:
一、異常類型
Error:一般是指嚴重的系統錯誤,與虛擬機器相關的問題,如系統崩潰,虛擬機器出錯,動態連結失敗等,這一類的錯誤一般無法修複或不可能捕獲,將導致應用程式中斷。
Exception:是指一些可以捕獲且可能恢複的異常情況,如數組下標越界ArrayIndexOutOfBoundsException、數字被零除產生異常ArithmeticException、輸入輸出異常IOException等。
可以知道Error屬於JVM需要負擔的責任,RuntimeException類是程式應該負擔的責任,受檢異常是具體應用負擔的責任。作為程式員關心的就是Exception。
1、非受檢異常
是指編譯器不要求強制處置的異常,一般是編程時的邏輯錯誤,是程式員應該避免的,RuntimeException類以及他的子類都是非受檢異常的,具體如下:
1)錯誤的類型轉換:ClassCastException
2)組下標越界:ArrayIndexOutOfBoundsException
3)null 指標訪問異常:NullPointerException
4)被零除產生異常:ArithmeticException
2、受檢異常
編譯器要求必須處置的異常,及程式運行時由於外界因素造成的一般性異常,具體如下:
1)沒有找到具體指定名稱的類異常:ClassNotFoundException
2)訪問不存在的檔案異常:FileNotFoundException
3)操作檔案異常:IOException
4)操作資料庫時發生異常:SQLException
Java要求Java程式必須捕獲或聲明所有的受檢異常,對於這類異常,如果程式不做處理,則將會帶來意想不到的結果,而非受檢異常可以不做任何處理。
二、捕獲異常語句
1、try……catch……finally……
try選定要捕獲異常的範圍,在執行時,catch後面括弧內的代碼會產生異常對象並拋出,然後用catch塊來處理異常。
finally不管是否有異常發生都要執行的語句塊,如資料庫的關閉。要注意:如果try語句塊中有一個明確的return語句,finally快也總是在return前執行。
2、throws 和 throw
throw:語句明確的拋出一個異常,必須是一個throwable 的類,或者new來建立一個執行個體:throw new XXException();
執行throw語句後,運行流程將立即停止throw的下一條語句也將暫停執行。
throws:如果一個方法a可以引發異常,而他本身並不對該異常進行處理,那麼a方法必須將這個異常拋給調用方法,以使程式能夠繼續執行下去。用法:method()throws Exception1,Exception2,。即throws用來聲明一個方法可能會拋出的所有異常,如果一個方法聲明的是受檢異常,那麼調用這個方法的類必須處理這個異常。可以使用try……catch……來捕獲,也可以在該方法上聲明throws。
public static void main(String[] args) { // TODO Auto-generated method stub int number = 0; try { System.out.println("aaaaaaaa"); number = Integer.parseInt(args[0]); System.out.println("bbbbbbbb"); } catch (Exception e) { // TODO: handle exception throw new ArrayIndexOutOfBoundsException("out of bounds"); //System.out.println("非法的數字"); } finally{ System.out.println("你輸入的數字為:"+number); } }
結果:
aaaaaaaa
你輸入的數字為:0
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: out of bounds
at com.wt.others.ThrowTest.main(ThrowTest.java:12)
原理:但拋出異常後將使用使用new在堆上建立異常對象,然後你的執行路徑被終止,並且從當前環境中彈出對異常對象的引用,此時異常處理機制接管程式,並開始找一個恰當的地方執行程式,這個恰當的地方就是例外處理常式,它的任務就是將程式從錯誤狀態中恢複。
public static void main(String[] args) { testThrows(args); } public static void testThrows(String[] tmp) { try { createThrows(tmp); } catch (Exception e) { // TODO: handle exception System.out.println("come from createThrows "); } } public static void test2Throws(String[] tmp) throws Exception { createThrows(tmp); } public static void createThrows(String[] tmp){ int num = 0; num = Integer.parseInt(tmp[0]); System.out.println("你輸入的數字為:"+num); }
throws和throw可以組合在一起使用,就是在捕獲異常後拋出一個明確的異常個調用者。
二者的區別:
throw是用在方法中的,throws是用在方法簽名之後的,在同一個地方使用這些的時候要注意,throws拋出異常的類型範圍要比throw的大才行。
public static void main(String[] args) { try { methodA(); } catch(Exception e) { // TODO: handle exception System.out.println(e.getMessage()); } methodB(); } public static void methodA() { try { System.out.println("come in A"); throw new RuntimeException("製造異常"); } finally { // TODO: handle exception System.out.println("用A的finally "); } } public static void methodB() { try { System.out.println("come in B"); return; //這裡返回,在執行完finally語句後才返回 } finally { // TODO: handle exception System.out.println("用B的finally "); } }
結果:
come in A
用A的finally
製造異常
come in B
用B的finally
3、getMessage和printStackTrace方法
getMessage:返回此throwable對象的詳細訊息字串
printStackTrace:將此throwable對象及其追蹤輸出至標準錯誤流
try{ fun();}catch(Exception e){ e.getMessage(e); // e.printStackTrace(e);}
三、自訂異常類
一般都選擇Exception作為父類,如下:
public class MyException extends Exception{ public MyException(){ super(); } public MyException(String msg){ super(msg); } public MyException(Throwable cause){ super(cause); } public MyException(String msg,Throwable cause){ super(msg, cause); }}
其實並不是所有的異常都需要處理,異常處理會佔用一定的資源,影響程式的執行效率。認真觀察異常的名字和行號,盡量減少try語句塊的體積,在處理異常的時候應該列印出該異常的堆棧資訊以方便調試使用。
對異常對象的清理並不需要過多的關心,因為他們都是用new在堆上建立的,記憶體回收行程會自動將他們清理掉。
Java異常處理機制