面向物件-異常
異常概述
什麼是異常(Exception:Java在執行過程當中出現的錯誤
Throwable
類是 Java 語言中所有錯誤或異常的超類。
異常:分為執行時異常和編譯時異常,我們需要了解的是執行時異常



JVM異常處理方式
JVM是怎麼處理異常的
main收到這個異常時,會做兩種處理方式
1.自己來去處理
2.自己處理不了,交給呼叫者jvm來處理
JVM內部會有一個異常處理機制,會把異常的名稱,異常資訊輸出到控制檯(建立一個異常物件)
new ArithmeticException("/by zero");

try_catch處理異常
自己處理異常
1.try...catch...finally
基本格式:
try { 可能出現異常的程式碼 }catch(異常型別){ }finally { 處理完異常最後做的處理 }
Try:用來檢測異常
Catch:用來捕獲異常
Finally:釋放資源
try { int a = 10 / 0; System.out.println(a); } catch (ArithmeticException a) { System.out.println(a);//java.lang.ArithmeticException: / by zero System.out.println("除數不能為0"); }
10/0;會建立一個異常物件
new ArithmeticException("/by zero");賦值給a,int a 接收不了,
此時就把異常物件傳給catch當中的引數a,能夠接收,就會執行了catch當中的內容,程式也沒有終止
只有在try出現問題的時候才會執行catch當中的內容
出現問題的時候catch處理完畢之後,後續的程式碼繼續執行
處理多個異常
try...catch處理多個異常
在try當中可能會出現不同的異常型別,此時可以使用多個catch來進行處理
try { int[] arr = { 10, 20, 30 }; System.out.println(arr[4]);// ArrayIndexOutOfBoundsException int a = 10 / 0;// ArithmeticException // 在try當中出現了異常,會立馬停止執行了try當中後續的程式碼 // 出現異常時會立馬跳到catch System.out.println("aaa"); System.out.println("aaa"); } catch (ArithmeticException a) { System.out.println("算數異常"); } catch (ArrayIndexOutOfBoundsException arr) { System.out.println("陣列越界異常"); }catch(Exception e) { System.out.println("其他異常"); }
Exception e不能寫在最上面,寫在上面會報錯,因為下面的永遠不會執行到,最常用的
不知道報什麼異常的時候,可以寫成
try { int[] arr = { 10, 20, 30 }; System.out.println(arr[4]);// ArrayIndexOutOfBoundsException int a = 10 / 0;// ArithmeticException } catch(Exception e) { System.out.println("其他異常"); }
JDK7之後處理多個異常
try { int[] arr = { 10, 20, 30 }; System.out.println(arr[4]);// ArrayIndexOutOfBoundsException int a = 10 / 0;// ArithmeticException System.out.println("aaa"); System.out.println("aaa"); //從jdk7之後可以這樣寫 } catch (ArithmeticException| ArrayIndexOutOfBoundsException e) { System.out.println("除數不能為0或者陣列越界"); }
執行時異常與編譯時異常
什麼是執行時異常?
所有的RuntimeException類及其子類成為執行時異常,在編譯時不會報錯,在執行過程程式終止執行
什麼是編譯時異常?
程式設計師必須顯示處理,否則程式就會發生錯誤無法通過編譯
編譯時異常發生的情況
FileInputStream fl = new FileInputStream("abc.txt");
執行時異常與編譯時異常的區別
執行時異常,程式設計師犯的錯誤,需要回來修改程式碼
編譯時異常在編譯某個程式的時候,有可能會這樣那樣的錯誤,
比如檔案找不到,這樣的異常就必須在編譯時處理
如果不處理就編譯不通過
try { FileInputStream fl = new FileInputStream("abc.txt"); }catch(Exception e) { System.out.println("發生異常了"); }
獲取異常資訊
常用方法:
1.獲取 異常資訊
,返回字串,引數
try { int a = 10/0; }catch(Exception e) { System.out.println(e.getMessage());/// by zero }
2.獲取 異常類名
和 異常資訊
try { int a = 10 / 0; } catch (Exception e) {//Exception e = new ArithmeticException("/ by zero") System.out.println(e.toString());//java.lang.ArithmeticException: / by zero System.out.println(e);//java.lang.ArithmeticException: / by zero }
3.獲取異常類名和異常資訊,及異常出現的位置(看異常資訊從下往上來去檢視)
try { int a = 10 / 0; } catch (Exception e) { e.printStackTrace(); }
throw丟擲異常
1.丟擲執行時異常,不需要處理
class Person { private int age; public void setAge(int age) { if (age > 0 && age <= 150) { this.age = age; } else { // 1.System.out.println("年齡不正確"); // 2.出現異常,終止程式執行 throw new RuntimeException("年齡不正確"); } } }
2.丟擲編譯時異常
class Person1 { private int age; public void setAge(int age) throws Exception {//丟擲異常 if (age > 0 && age <= 150) { this.age = age; } else { // 3.編譯時異常 throw new Exception("年齡不正確"); } } }
丟擲了一個編譯時異常,必須要得要有人處理
如果不處理,必須繼續往上拋,拋給方法呼叫者
Person1 per = new Person1(); per.setAge(-10);
此時由於setAge內部丟擲了一個異常,在呼叫該方法時必須得要處理
1.必須要處理異常
Person1 per = new Person1(); try { per.setAge(-10); } catch (Exception e) { e.printStackTrace(); }
2.繼續往上丟擲
自己不處理,拋給main方法呼叫者jvm處理,同樣是控制檯報出錯誤
public static void main(String[] args) throws Exception { Person1 per = new Person1(); per.setAge(-10); }
throw與throws的區別
throw:
用在方法內,跟的是異常物件名稱
只能丟擲一個異常物件
表示丟擲異常
throws:
用在方法生命後面,跟的是異常類名
可以跟多個異常類名,中間使用逗號隔開
表示丟擲異常,由方法呼叫者來處理
finally
fianlly特點
:
被finally控制的語句一定會被執行到
//只要執行了try,就會執行finally try { System.out.println(10 / 0); } catch (Exception e) { System.out.println("錯誤:除數不能為0"); } finally { System.out.println("執行了finally"); }
特殊情況
:在執行finally之前jvm退出了
try { System.out.println(10 / 0); } catch (Exception e) { System.out.println("錯誤:除數不能為0"); //System.exit(0); return;//終止當前方法執行,是不能阻止finally } finally { System.out.println("執行了finally");//exit,jvm停止了,不會執行 } System.out.println("end");//不會被執行,方法已經終止了
finally作用
:
用來釋放資源,在IO操作中經常見到
退出程式
:
retrun,終止當前方法執行,並不能阻止finally
exit(0),jvm停止了,finally就不會執行
finally返回值問題
int x = 10; try { x = 20; System.out.println(1 / 0); return x; } catch (Exception e) { x = 30; return x;//return返回的是當時的值 } finally {//finally一般不做return,只作資源的釋放 x = 40; } }
System.out.println(Demo8.test());//30
自定義異常
為什麼自定義異常:
系統自帶的異常類名稱有很多,通過型別就能看出是什麼異常,算術異常,空指標異常,陣列越界異常
自己也想丟擲一個異常,類名是自己定義的,通過類名就能知道是什麼型別的異常
自定義執行時的異常
:
1.定義一個類繼承RuntimeException
2.丟擲異常時,丟擲自己定義的異常類名
class AgeBoundsException extends RuntimeException{ }
throw new AgeBoundsException();

自定義編譯時異常
:
1.定義一個類繼承Exception
class AgeBoundsException extends Exception{ }
2.丟擲異常時,丟擲自己定義的異常類名
public static void main(String[] args) throws AgeBoundsException { throw new AgeBoundsException(); }

以上兩種報異常的方法都是不帶引數的
找方法的eclipse的快捷鍵:Ctrl+O
自定義帶引數的異常
1.定義一個類繼承RuntimeException或者Exception
在類當中提供一個有引數的構造方法
把引數傳給父類構造器
class AgeBoundsException extends Exception{ AgeBoundsException(String message){ super(message); } }
2.丟擲異常時,丟擲自己定義的異常類名並且傳入對應的引數
public static void main(String[] args) throws AgeBoundsException { throw new AgeBoundsException("年齡出問題了"); }