異常:
在運行期間發生的不正常情況。
在JAVA中用類的形式對異常的情況進行了類的封裝。
這些描述不正常情況的類就稱為異常類。 異常類就是java通過面向對象的思想將問題封裝成了對象。用異常類對問題進行描述,不同的問題用不同的類進行具體的描述,比如,空指針 腳標越界 等等......
以前將正常流程代碼和處理異常的代碼相結合,現在是將正常流程代碼和處理異常的代碼分開,這樣就提高了閱讀性。
體系:
問題很多,對應的異常類就有很多,通過對這些異常類共性的不斷向上提取,就形成了異常體系。Throwable。
這個體系有個特點,就是Throwable及其子類都具有可拋性。即被throw throws拋。
Throwable:
分為兩大類:
Error(一般不可處理的問題)由JVM拋出的嚴重性問題,一般不進行針對性處理,而是直接修改程序。已經讓虛擬機不正常了,這是錯誤。
Exception(可處理)
異常的分類:
編譯時被檢測異常:只要是Exception及其子類,除了RuntimeException及其子類;
這種異常一但出現,就在編譯時出現錯誤,希望能夠得到針對性的處理。
編譯時不被檢測異常(運行時異常):RuntimeException及其子類;該類是JVM正常運行期間拋出的異常超類;
這種異常一但出現,無法讓功能繼續運行,一般是調用者導致的或者 引發了內部狀態的改變導致的,
這種異常一般不處理,直接編譯通過,在運行的時候直接讓調用者調用的程序停止,讓調用者對代碼進行修正。
簡單示例:
JAVA編譯器,一般是先檢查語法錯誤,再檢查邏輯錯誤。
這里腳標越界
1 class Text{ 2 public static void main(String[] args){ 3 int[] a=new int[3]; 4 A Dome=new A(); 5 Dome.show(a, 3); 6 } 7 8 } 9 class A{ 10 void show(int[] a,int b){ 11 System.out.print(a[b]);//throw new ArrayIndexOutOfBoundsException(b); 12 } 13 14 }
實際上在11行會進行對象的封裝,然后把問題反饋給調用者(main)
然而main並沒有處理的方法他也只能把問題已同樣的方法拋給JVM
JVM便會把問題打印在控制台上,讓調用者去處理(在以后開發的時候這些異常存儲在日志中)。
代碼拋出了異常,該代碼下面的代碼將不會執行,除了finally。
如果異常的代碼catch處理了,那么該異常代碼下面的代碼會繼續執行下去。
自定義異常類:
自定義的異常類,要么繼承Exception,要么繼承RuntimeException;
當繼承Exception時,一定要聲明異常,否則編譯失敗,(就好比你有一塊變質的面包,你直接給別人,別人吃了GG,所以一定要聲明,讓別人有處理的辦法)
但是如果繼承的是RuntimeException的話,可以編譯通過。
1 class Text{ 2 public static void main(String[] args) throws FuShuIndextException{ 3 int[] a=new int[3]; 4 Text1 Dome=new Text1(); 5 Dome.show(a, -1); 6 } 7 8 } 9 class Text1{ 10 void show(int[] a,int b) throws FuShuIndextException{ 11 if(b<0){ 12 throw new FuShuIndextException("數組腳標不能為負"); 13 } 14 15 } 16 17 } 18 class FuShuIndextException extends Exception{ 19 FuShuIndextException(String a){ 20 super(a); 21 } 22 }
throw new FuShuIndextException("數組腳標不能為負"); 打印這句話只需要異常類里面有對應的構造函數,該構造函數調用其父類的方法。
在這里我是用了聲明(拋出 throws)的方法解決異常,所以異常代碼后面的代碼將不會不執行到,
但是這個數組腳標不能為負數的異常是可以用catch的解決的,下面我會用catch的方法來處理這個的異常。
聲明和捕捉:
處理異常的兩個方法。
聲明:聲明異常的目的就是為了讓調用者處理異常,所以如果聲明了異常,那么一定要處理。要么throws要么try catch。
捕捉:try(需要被檢測異常的代碼) catch(處理異常的代碼) finally(里面的代碼一定會被執行到),即對異常進行針對性的處理。
1.try catch finally
2.try catch(可以多個)沒有需要釋放的資源
3.try finally異常無法catch處理,但是需要釋放資源
1 class Text{ 2 public static void main(String[] args) { 3 int[] a=new int[3]; 4 Text1 Dome=new Text1(); 5 try{ 6 Dome.show(a, -1); 7 } 8 catch(FuShuIndextException e){ 9 // System.out.println(e); 10 // System.out.println(e.toString()); 11 // System.out.println(e.getMessage()); 12 // e.printStackTrace(); 13 14 }finally{ 15 System.out.println("finall中一定會被執行到的代碼"); 16 } 17 System.out.println("解決了問題后依然會運行的代碼"); 18 19 20 } 21 22 } 23 class Text1{ 24 void show(int[] a,int b) throws FuShuIndextException{ 25 if(b<0){ 26 throw new FuShuIndextException("數組腳標不能為負"); 27 } 28 } 29 30 } 31 class FuShuIndextException extends Exception{ 32 FuShuIndextException(String a){ 33 super(a); 34 } 35 }
第9-12行的代碼是打印異常的信息即"數組腳標不能為負"輸出為
FuShuIndextException: 數組腳標不能為負
FuShuIndextException: 數組腳標不能為負
數組腳標不能為負
FuShuIndextException: 數組腳標不能為負
at Text1.show(Text.java:26)
at Text.main(Text.java:6)
第9行等價於第10行,它默認的是e.toString
第12行,JVM默認的異常處理機制就是調用了這個方法
異常處理的原則:
1.函數內容如果拋出了需要檢測的異常,那么函數上一定要聲明或者try catch捕捉否則編譯失敗
2.如果調用到了聲明異常的函數,那么調用者一定要聲明或者try catch捕捉否則編譯失敗
3.能夠處理的異常用try catch自己解決,不能處理的異常用throw告訴調用者,讓調用者解決
4.一個功能如果拋出了多個異常,那么調用時要有相對應的catch進行針對性的處理。
內部有幾個需要被檢測的異常,就要有對應的catch來解決異常
但是當多catch出現的時候要注意父類的catch要放在最后面,否則編譯失敗,因為父類catch下面的catch都變成了廢話
異常的注意事項:
子類覆蓋父類,就只能拋出父類的異常,或者子類或者子集
父類沒有異常,子類絕對不能拋出異常,只能try catch