六、java 異常處理
一、JAVA異常的體系結構
① Error:Java虛擬機器無法解決的嚴重問題;一般不編寫正對性的程式碼處理;
② Exception:其他因為程式設計錯誤或偶然的外在因素導致的一般性問題;可以進行異常處理;處理完後不影響程式的執行;
a.Exception又可以分為執行時異常和編譯時異常;
①編譯時異常(check):編譯報錯,要求必須處理,否則編譯不通過;例如IOException、ClassNotFoundException
②執行時異常(unchecked RuntimExceprion):一般不處理;例如:NullPointerExcepion(空指標異常),ArrayIndexOutOfBoundsException(陣列越界異常),ClassCastExcetption(類轉換異常),NumberFormateException...
二、異常處理的兩種方式:
①不直接處理,往呼叫層丟擲異常 throw + 異常型別;
②處理異常:try{}catch(){}finally{}
一下為異常處理的throw的方式:丟擲異常,單元測試會報相應的NumberFormatException異常,無法執行到丟擲異常後的語句;
1 @Test 2 public void testx() { 3 String str = "abc"; 4 int num = Integer.parseInt(str); 5 System.out.println("hello -1");6 throw new NumberFormatException(); 7 //System.out.println("hello -2"); 8 }
一下為異常處理的try catch的方式:單元測試通過,並且執行了System.out.println("hello -2");
1 @Test 2 public void test1() { 3 String str = "abc"; 4 try { 5 6 int num = Integer.parseInt(str);7 System.out.println("hello -1"); 8 }catch(NumberFormatException e) {//如果NumberFormatException換成時 NullPointerException則還是丟擲異常 9 System.out.println("出現數值轉換異常了。。。。"); 10 String mes = e.getMessage(); 11 System.out.println(mes);//常用異常處理方式1 12 e.printStackTrace();//常用異常處理方式2 13 14 } 15 System.out.println("hello -2"); 16 }
三、過程:
過程一、“拋”;程式在正常執行過程中,一旦出現異常,就會在異常程式碼處生成一個對應異常的物件;並將此物件丟擲;
一旦丟擲異常,其後面的程式碼不再執行;
關於異常物件的產生,1,系統生成 的,2.手動生成一個異常物件並且丟擲;throw;
過程二:“抓”:可以理解為異常處理方式:
try catch finally的使用:
try{
//可能出現異常的程式碼
}catch(異常型別1 變數名){
//處理異常方式1
}catch(異常型別2 變數名){
//處理異常方式2
}catch(異常型別3 變數名){
//處理異常方式3
}
........
finally{
//一定會執行的程式碼
}
說明:
1.finaly 是可選的
2。使用try將肯出現的程式碼包裝起來,在執行過程中,一旦出現異常,就會生成一個對應異常類的物件,
根據此物件的型別,去catch中進行匹配
3.一旦try中的異常物件匹配到某一個catch時,就進入catch中進行異常處理,一旦處理完成就跳出try-catch結構(在沒有finally的情況),
繼續執行後面的程式碼;
4.catch中的異常型別如果沒有子父類關係,則誰宣告在上面,誰宣告在下,無所謂,
catch中的異常型別如果滿足子父類關係,則要求子類在上,父類在下,否則報錯;
5.常用的異常處理方式 a.String getMessage() ;b printStackTrace();
6.在try中宣告的變數,出了try結構就不能呼叫;
7.try catch finally 結構可以巢狀
例如:
@Test public void test2() { int a= 10; int b = 0; try { System.out.println(a / b); } catch(ArithmeticException e){ e.printStackTrace(); }finally { System.out.println("finally~~~"); // : handle finally clause } }
該程式 Junit通過,控制檯列印異常和finally~~~;因為程式執行到 System.out.println(a / b); b=0所以 出現了錯誤,生成ArithmeticException物件,與catch中的異常進行匹配,匹配上後,進行異常處理,處理完成,執行finally中的程式碼;
1 @Test 2 public void test3() { 3 4 Day16ErrorAndExceptionDiscriable6 tt = new Day16ErrorAndExceptionDiscriable6(); 5 6 System.out.println(tt.finallyTest()); 7 } 8 9 public int finallyTest() { 10 try { 11 int[] arr = new int[10]; 12 //System.out.println(arr[10]); 開啟或者關閉,return都是3; 3之前是inally~~~ 13 return 0; 14 } catch(ArrayIndexOutOfBoundsException e){ 15 e.printStackTrace(); 16 return 1; 17 }finally { 18 System.out.println("finally~~~"); 19 return 3; 20 // : handle finally clause 21 } 22 }
必須要處理的異常:如若需要呼叫時,必須要處理異常,或者是再往上丟擲異常;
1 public void method() throws FileNotFoundException,IOException{ 2 File file = new File("hello.txt"); 3 FileInputStream fis = null; 4 fis = new FileInputStream(file); 5 int data = fis.read(); 6 while(data != -1) { 7 data = fis.read(); 8 } 9 fis.close(); 10 } 11 12 public void method2() throws FileNotFoundException,IOException{ 13 method(); 14 }
1 @Test 2 public void test4() { 3 File file = new File("hello.txt"); 4 FileInputStream fis = null; 5 try { 6 fis = new FileInputStream(file); 7 int data = fis.read(); 8 while(data != -1) { 9 data = fis.read(); 10 } 11 } catch (FileNotFoundException e) { 12 e.printStackTrace(); 13 }catch (IOException e) { 14 e.printStackTrace(); 15 }finally { 16 try { 17 if(fis != null) { 18 fis.close(); 19 } 20 } catch (IOException e) { 21 // TODO Auto-generated catch block 22 e.printStackTrace(); 23 } 24 } 25 26 27 }
體會:
try catch finally真正把異常處理掉,
throws 的方式只是將異常拋給了方法的呼叫者,並沒有真正的處理掉異常
開發中,如何選擇try catch finally OR throws?
1.如果父類中被重寫的方法沒有throws,則子類重寫的方法也不能throws,意味著如果子類重寫的方法有異常,必須用try catch finally;
2.執行的方法A中,先後又呼叫了另外的幾個方法,這幾個方法是遞進的關係執行的,建議這幾個方法使用throws的翻翻,而執行的方法A可以考慮使用try catch finally;