目錄java
終於完成本學期的最後一門考試,考試周的我,邊複習通訊之傅里葉變換,邊學習Java的新知識。雖然好久沒更,可是私底下的筆記滿滿,特意總結一波。
總結什麼呢?異常!嗯?異常?最近卻是人有些異常……複習到一兩點,早上早早起來刷題,不異常纔怪。異常嘛,很好理解,就是本該正常的事情出了問題嘛。
這時咱們回想咱們以前寫過一個再簡單不過的例子:計算兩個整數相除。二話不說,直接就能夠寫出以下代碼,對吧。編程
public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.println("Enter two integers: "); int num1 = input.nextInt(); int num2 = input.nextInt(); System.out.println(num1 / num2); }
這短短的代碼中就存在着隱患,而這個隱患有可能就會演變成異常。什麼狀況呢?咱們知道,在Java的整數計算中,若是除數爲零,計算式將會是沒有任何意義的。帶着咱們的猜測,編譯運行,不出所料,它飄紅了。
學習
因而,咱們對紅字進行分析,得出結論:一個名爲ArthmeticException的異常在執行main方法的第17行時發生:除數爲零。清清楚楚,明明白白。
能夠看到,異常一旦發生,程序就將終止,並且這種拋出異常的機制,可以讓咱們有效地找到問題所在,並及時解決問題。異常機制的存在,就是爲了更好地解決問題,保證程序的健壯性。
因此,咱們試圖修改代碼,讓它在方法中實現:測試
public static int quotient(int num1, int num2) throws ArithmeticException{ if (num2 == 0) { throw new ArithmeticException("Divisor can not be zero"); } return num1 / num2; }
在main方法中調用查看結果:優化
int num1 = input.nextInt(); int num2 = input.nextInt(); try { System.out.println(QuotientWithMethod.quotient(num1, num2)); }catch (ArithmeticException e) { System.out.println(e.getMessage()); }
繼續測試(固然爲了測試,咱們這裏拋出了一個運行時異常,本能夠不拋):
指針
throw new ArithmeticException("Divisor can not be zero");
對象。throws ArithmeticException
。try{...}catch (ArithmeticException e){...}
並執行咱們但願處理異常的語句,System.out.println(e.getMessage());
。固然,上述的例子集拋出異常、聲明異常及處理異常於一身,可是異常的內容可不只僅是這麼簡單,咱們在以後的內容中來探一探異常的究竟:code
先來看一下異常的類繼承圖,當是不徹底統計的,由於還有還多好多的異常等待着被探索。
對象
經過圖片咱們能夠明顯的發現,這些異常的命名很是好認,果然見名知義。Throwable
是全部異常的頂級父類,在它的下面有兩個大類:Exception
和Error
。下面是官方文檔對二者進行的解釋:blog
合理的應用程序出現的不該該捕獲的嚴重問題 ,合理指的是語法和邏輯上。繼承
與虛擬機相關,如系統崩潰、虛擬機錯誤、動態連接失敗等
也叫運行時異常,由Java虛擬機拋出,只是容許編譯時不檢測,在沒有捕獲或者聲明的狀況下也同樣可以經過編譯器的語法檢測,因此不須要去親自捕獲或者聲明,固然要拋出該類異常也是能夠的。典型的異常類型:Error及其子類異常,RuntimeException及其子類異常。注意:RuntimeException表明的是一類編程錯誤引起的異常:算數異常、空指針異常、索引越界異常、非法參數異常等等,這些錯誤若是代碼編寫方面沒有任何漏洞,是徹底能夠避免的,這也是不須要捕獲或者聲明的緣由,也有助於簡化代碼邏輯。
也叫編譯時異常,Java認爲受檢異常須要在編譯階段進行處理, 必須在顯式地在調用可能出現異常的方法時捕獲(catch),或者在聲明方法時throws異常類型,不然編譯不會經過。除了上面提到的Exception及其子類都屬於受檢異常,固然,不包括上面提到的RuntimeException。
咱們上面提到,咱們沒法去直接處理不受檢異常,可是咱們必須強制地對可能發生受檢異常(編譯時異常)的行爲作處理,處理方法主要有如下:
public void m1() throws ClassNotFoundException, IOException { //to do something }
try{...}catch{...}
語句捕獲,並在catch塊中處理該異常。public void m3() { try { m1(); } catch (ClassNotFoundException e) { //to do something } catch (IOException e) { //to do something } }
也能夠直接捕獲Exception的實例,由於它是這些異常的父類,可是上面的捕獲異常引起的錯誤會更加直接一些。
public void m2() { try { m1(); } catch (Exception e){ //do something } }
若是處理不了,就一直向上拋,直到有完善解決的辦法出現爲止。固然咱們也能夠自行拋出系統已經定義的異常:
public void m2(int i) throws IOException, ClassNotFoundException { if (i >1) throw new IOException("!"); throw new ClassCastException(); }
須要注意的是:
咱們知道,程序發生錯誤時,系統會自動拋出異常。那麼,咱們若是想獨家定製一個屬於本身的異常能夠不?答案顯然是能夠的,情人節快到了,直接自定義一個異常:
class noGirlFriendException extends Exception{ noGirlFriendException(){ } noGirlFriendException(String msg){ super(msg); } }
須要注意的是:
//下面的形式錯誤! public static void main(String[] args) { try { System.out.println(1 / 0); } catch (Exception e) { e.printStackTrace(); } catch (ArithmeticException e) { System.out.println(e.getMessage()); } }
try { System.out.println(1 / 0); } catch (ArithmeticException | NullPointerException e) { //捕獲多異常時,異常變量被final隱式修飾 //!false: e = new ArithmeticException(); System.out.println(e.getMessage()); }
本文參考諸多資料,並加上自身理解,若有敘述不當之處,還望評論區批評指正。關於異常,還有一部份內容,下篇進行總結,晚安。
參考資料:
https://stackoverflow.com/questions/6115896/understanding-checked-vs-unchecked-exceptions-in-java
https://www.programcreek.com/2009/02/diagram-for-hierarchy-of-exception-classes/