程序在運行過程當中出現不正常狀況。是對問題的描述,將問題進行對象的封裝。java
問題也是現實生活中一個具體的事物,也能夠經過Java的類的形式進行描述,並封裝成對象。數據庫
一種是嚴重的問題,一種是非嚴重的問題。數組
對於非嚴重的:Java經過Exception類進行描述。
對於Exception可使用針對性的處理方式進行處理。
不管Error仍是Exception都具備一些共性內容。
好比:不正常狀況的信息,引起緣由。jvm
Throwable |--Error |--Exception |--RuntimeException
異常體系的特色:
異常體系中的全部類以及被創建的對象都具有可拋性。ide
try { 須要被檢測的代碼 } catch(異常類 變量) { 處理異常的代碼(處理方式) } finally { 必定會執行的語句; }
String getMessage();
String toString();
void printStackTrace();函數
class Demo { int div(int x,int y) { return x/y; } } public class ExceptionDemo { public static void main(String[] args) { Demo d = new Demo(); try { int z = d.div(1,0); System.out.println(z); } catch (Exception e) { //Exception e = new ArithmeticExceptin(); System.out.println(e.getMessage()); // /by zero System.out.println(e.toString()); // 異常名稱:異常信息 e.printStackTrace(); // 異常名稱:異常信息,異常出現的位置 //(jvm默認的處理異常的機制就是在調用printStackTrace()方法) } System.out.println("over"); } }
運行結果this
/ by zero java.lang.ArithmeticException: / by zero java.lang.ArithmeticException: / by zero at Demo.div(ExceptionDemo.java:3) at ExceptionDemo.main(ExceptionDemo.java:10) over
class Demo { int div(int x,int y) throws Exception { return x/y; } } public class ExceptionDemo1 { public static void main(String[] args) throws Exception { Demo d = new Demo(); int y = d.div(1,0); System.out.println(y); System.out.println("over"); } }
class Demo { int div(int x,int y) throws Exception { return x/y; } } public class ExceptionDemo2 { public static void main(String[] args) { Demo d = new Demo(); int y = d.div(1,0); System.out.println(y); System.out.println("over"); } }
上述代碼編譯會提示:code
Error:(9, 22) java: 未報告的異常錯誤java.lang.Exception; 必須對其進行捕獲或聲明以便拋出
咱們對可能出現的異常加以處理:對象
class Demo { int div(int x,int y) throws Exception { return x/y; } } public class ExceptionDemo3 { public static void main(String[] args) { Demo d = new Demo(); try { int y = d.div(1,0); System.out.println(y); } catch (Exception e) { System.out.println(e.toString()); } System.out.println("over"); } }
運行結果:繼承
java.lang.ArithmeticException: / by zero over
對可能出現異常的div方法進行處理以後,程序能夠正常編譯運行。
1.聲明異常時,聲明爲更爲具體的異常,這樣能夠處理得更具體。
2.方法聲明有幾個異常,對應就有幾個catch塊。(不要定義多餘的catch塊)
若是多個catch塊中的異常出現繼承關係,父類異常catch塊放在最下面。
class Demo { int div(int x,int y) throws ArithmeticException,ArrayIndexOutOfBoundsException { int[] arr = new int[x]; System.out.println(arr[3]); return x/y; } } public class ExceptionDemo4 { public static void main(String[] args) { Demo d = new Demo(); try { int y = d.div(2,0); } catch (ArithmeticException e) { System.out.println("被零除了"); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("數組角標越界"); } } }
運行結果:
數組角標越界
上述代碼中顯然有兩個一場出現,可是當方法中出現一個異常以後方法會中止運行,不會繼續執行下去。
項目中會出現特有的問題,而這些問題並未被Java描述並封裝對象。因此對這些特有的問題能夠按照Java的對問題封裝的思想,將特有的問題,進行自定義的異常封裝。
需求:在本程序中,對於除數是負數,也視爲是錯誤的。
當在函數內部出現了throw拋出異常對象,那麼就必需要給對應的處理。
要麼在內部使用try catch處理。
要麼在函數上聲明讓調用者處理。
class FuShuException extends Exception { } class Demo { int div(int x,int y) throws FuShuException{ if(y<0) { throw new FuShuException();//經過throw關鍵字手動拋出一個自定義異常對象 } return x/y; } } public class ExceptionDemo5 { public static void main(String[] args) { Demo d = new Demo(); try { int y = d.div(1,-1); System.out.println(y); } catch (FuShuException e) { System.out.println(e.toString()); System.out.println("除數出現負數了"); } } }
運行結果
FuShuException 除數出現負數了
咱們能夠發現以上的代碼運行的結果中只有異常的名稱,卻沒有異常的信息。由於咱們並未在自定義的異常中定義具體信息。
由於父類中已經把異常信息的操做完成了。因此子類只要在構造時,將異常信息傳遞給父類經過super語句,就能夠經過getMessage方法獲取自定義的異常信息。
class FuShuException extends Exception { private int value; FuShuException(){ super(); } FuShuException(String message,int value) { super(message); this.value = value; } public int getValue() { return value; } } class Demo { int div(int x,int y) throws FuShuException{ if(y<0) { throw new FuShuException("--被零除了--",y);//經過throw關鍵字手動拋出一個自定義異常對象 } return x/y; } } public class ExceptionDemo5 { public static void main(String[] args) { Demo d = new Demo(); try { int y = d.div(1,-1); System.out.println(y); } catch (FuShuException e) { System.out.println(e.toString()); System.out.println("除數出現了負數:"+e.getValue()); } } }
運行結果:
FuShuException: --被零除了-- 除數出現了負數:-1
自定義異常必須是是自定義類繼承Exception
異常體系中的異常類和異常對象都具有可拋性,這個可拋性是Throwable這個體系中獨有的特色。只有這個體系中的類和對象才能夠被throw和throws操做。
異常分兩種
RuntimeException是Exception中的一個特殊的子類。
若是在函數內容中拋出異常,函數上能夠不用聲明。
若是在函數上聲明瞭異常,調用者能夠不用進行處理。
之因此不用在函數上聲明是由於不須要讓調用者處理,當該異常發生,程序但願中止,對代碼進行修正,而不是去讓調用者處理。
自定義異常時,若是該異常發生,沒法再繼續進行運算,就讓自定義異常繼承RuntimeException。
class FuShuException extends RuntimeException{ FuShuException(String message) { super(message); } } class Demo { int div(int x,int y) { //函數上爲聲明異常也能夠正常編譯 if (y < 0) { throw new FuShuException("--除數爲負數--");//在函數內容中拋出異常 } else if(y == 0){ throw new ArithmeticException("--除數爲零--");//在函數內容中拋出異常 } return x/y; } } public class ExceptionDemo6 { public static void main(String[] args) { Demo d = new Demo(); try { int y = d.div(1,-1); } catch (FuShuException e) { System.out.println(e.toString()); } catch (ArithmeticException e) { System.out.println(e.toString()); } } }
try { } catch () { } finally { }
finally中存放的是必定會被執行(不管是否有異常)的代碼,即便catch中有return語句。
finally只有一種狀況不會被執行,當代碼執行到System.exit(0);
例如:若是須要對數據庫進行操做,不管有沒有成功鏈接上數據庫,在最後操做完成的時候,都須要斷開數據庫的鏈接,以釋放有限的資源。
try { } finally { }
將正常流程代碼和問題處理代碼相分離,加強代碼可讀性。
有圓形和長方形,均可以獲取面積,對於面積,若是出現非法的數值,視爲是獲取面積出現問題。
出現的問題經過異常來表示。(使用異常能夠,使問題處理代碼和正常流程代碼分開)
interface Shape { void getArea(); } class InvaidValueException extends RuntimeException {//若是一個傳入一個圖形的參數有錯誤,咱們沒法對其進行有效的處理,只拋出異常便可,因此繼承RuntimeException InvaidValueException(String message) { super(message); } } class Rec implements Shape { private double len,wid; Rec(double len,double wid) { if(len <= 0 || wid <= 0) throw new InvaidValueException("非法值"); this.len = len; this.wid = wid; } @Override public void getArea() { System.out.println(wid*len); } } class Circle implements Shape { private double r; public static final double PI = 3.14; Circle(double r) { if(r <= 0) throw new InvaidValueException("非法值"); this.r = r; } @Override public void getArea() { System.out.println(r*r*PI); } } public class ExceptionDemo7 { public static void main(String[] args) { Rec R = new Rec(1,2); R.getArea(); Circle C = new Circle(-1); C.getArea(); System.out.println("over"); } }
上述程序的運行結果爲:
2.0 Exception in thread "main" InvaidValueException: 非法值 at Circle.<init>(ExceptionDemo7.java:28) at ExceptionDemo7.main(ExceptionDemo7.java:41)