你之因此能優於別人,正是由於你堅持了別人所不能堅持的。
本文相關代碼在個人Github,歡迎Star~
https://github.com/zhangzhibo1014/DaBoJava
異常指不期而至的各類情況,異常是程序中的一些錯誤,但並非全部的錯誤都是異常,而且錯誤有時候是能夠避免的。java
好比說,你的代碼少了一個分號,那麼運行出來結果是提示是錯誤 java.lang.Error
;若是你用 System.out.println(11/0)
,那麼你是由於你用0作了除數,會拋出 java.lang.ArithmeticException
的異常。git
要理解Java異常處理是如何工做的,你須要掌握如下三種類型的異常:程序員
異常都是從 Throwable
類派生出來的,而 Throwable
類是直接從 Object
類繼承而來。github
全部的異常類是從 java.lang.Exception
類繼承的子類。而 Exception
異常下又主要分爲兩大類異常,一個是派生於 RuntimeExcption
的異常,一個是除了 RuntimeExcption
體系以外的其餘異常。數組
RuntimeExcption
異常(運行時異常)一般有如下幾種:安全
null
指針異常 | 描述 |
---|---|
ArithmeticException | 當出現異常的運算條件時,拋出此異常。例如,一個整數"除以零"時,拋出此類的一個實例。 |
ArrayIndexOutOfBoundsException | 用非法索引訪問數組時拋出的異常。若是索引爲負或大於等於數組大小,則該索引爲非法索引。 |
ArrayStoreException | 試圖將錯誤類型的對象存儲到一個對象數組時拋出的異常。 |
ClassCastException | 當試圖將對象強制轉換爲不是實例的子類時,拋出該異常。 |
IllegalArgumentException | 拋出的異常代表向方法傳遞了一個不合法或不正確的參數。 |
IllegalMonitorStateException | 拋出的異常代表某一線程已經試圖等待對象的監視器,或者試圖通知其餘正在等待對象的監視器而自己沒有指定監視器的線程。 |
IllegalStateException | 在非法或不適當的時間調用方法時產生的信號。換句話說,即 Java 環境或 Java 應用程序沒有處於請求操做所要求的適當狀態下。 |
IllegalThreadStateException | 線程沒有處於請求操做所要求的適當狀態時拋出的異常。 |
IndexOutOfBoundsException | 指示某排序索引(例如對數組、字符串或向量的排序)超出範圍時拋出。 |
NegativeArraySizeException | 若是應用程序試圖建立大小爲負的數組,則拋出該異常。 |
NullPointerException | 當應用程序試圖在須要對象的地方使用 null 時,拋出該異常 |
NumberFormatException | 當應用程序試圖將字符串轉換成一種數值類型,但該字符串不能轉換爲適當格式時,拋出該異常。 |
SecurityException | 由安全管理器拋出的異常,指示存在安全侵犯。 |
StringIndexOutOfBoundsException | 此異常由 String 方法拋出,指示索引或者爲負,或者超出字符串的大小。 |
UnsupportedOperationException | 當不支持請求的操做時,拋出該異常。 |
通常來講,RuntimeException
都是代碼邏輯出現問題。微信
非 RuntimeException
(受檢異常,Checked Exception)通常有:網絡
異常 | 描述 |
---|---|
ClassNotFoundException | 應用程序試圖加載類時,找不到相應的類,拋出該異常。 |
CloneNotSupportedException | 當調用 Object 類中的 clone 方法克隆對象,但該對象的類沒法實現 Cloneable 接口時,拋出該異常。 |
IllegalAccessException | 拒絕訪問一個類的時候,拋出該異常。 |
InstantiationException | 當試圖使用 Class 類中的 newInstance 方法建立一個類的實例,而指定的類對象由於是一個接口或是一個抽象類而沒法實例化時,拋出該異常。 |
InterruptedException | 一個線程被另外一個線程中斷,拋出該異常。 |
NoSuchFieldException | 請求的變量不存在 |
NoSuchMethodException | 請求的方法不存在 |
受檢異常是編譯器要求必須處理的異常,必須使用 try catch
處理,或者使用 throw
拋出,交給上層調用者處理。函數
當程序運行時數據出現錯誤或者咱們不但願發生的狀況出現的話,能夠經過拋出異常來處理。spa
異常拋出語法:
throw new 異常類(); //拋出異常 public static void fun1() { Integer a = 1; Integer b = null; // 若是 a 或者 b 爲 null 則拋出異常 if (a == null || b == null) { throw new NullPointerException(); } else { System.out.println(a+b); } }
throws
用於聲明異常,表示該方法可能會拋出的異常。若是聲明的異常中包括 checked
異常(受檢異常),那麼調用者必須捕獲處理該異常或者使用 throws
繼續向上拋出。throws
位於方法體前,多個異常之間使用 ,
分割。
public static void main(String[] args) throws FileNotFoundException { fun2(); } //聲明異常 public static void fun2() throws FileNotFoundException { new FileInputStream("a.txt"); }
throw
用於拋出異常對象,後面跟的是異常對象;throw
用在函數內。throws
用於拋出異常類,後面跟的異常類名,能夠跟多個,用逗號隔開。throws
用在函數上一般拋出異常後,還須要將異常捕獲。使用 try
和 catch
語句塊來捕獲異常,有時候還會用到 finally
。
對於上述三個關鍵詞所構成的語句塊,try
語句塊是必不可少的,catch
和 finally
語句塊能夠根據狀況選擇其一或者全選。你能夠把可能發生錯誤或出現問題的語句放到 try
語句塊中,將異常發生後要執行的語句放到 catch
語句塊中,而 finally
語句塊裏面放置的語句,無論異常是否發生,它們都會被執行。
捕獲異常對於系統而言,其開銷很是大,因此應儘可能減小該語句塊中放置的語句。
public class Demo1 { public static void main(String[] args) { try{ //要檢查的程序語句 System.out.println("I am try block."); Class<?> tempClass = Class.forName(""); // 聲明一個空的Class對象用於引起「類未發現異常」 System.out.println("Bye! Try block."); }catch (ClassNotFoundException e) { //異常發生時的處理語句 System.out.println("I am catch block."); e.printStackTrace(); //printStackTrace()的意義在於在命令行打印異常信息在程序中出錯的位置及緣由 System.out.println("Goodbye! Catch block."); }finally { //必定會執行的語句 System.out.println("I am finally block."); } } }
注意下面事項
catch
不能獨立於 try
存在。try/catch
後面添加 finally
塊並不是強制性要求的。try
代碼後不能既沒 catch
塊也沒 finally
塊。try, catch, finally
塊之間不能添加任何代碼。finally
頗有用,主要用戶關閉資源。不管是否發生異常,資源都必須進行關閉在一段代碼中,可能會因爲各類緣由拋出多種不一樣的異常,而對於不一樣的異常,咱們但願用不一樣的方式來處理它們,而不是籠統的使用同一個方式處理,在這種狀況下,可使用異常匹配,當匹配到對應的異常後,後面的異常將再也不進行匹配。
public class Demo2 { public static void main(String[] args) { try{ new FileInputStream(""); } catch (FileNotFoundException e) { System.out.println("IO 異常"); } catch (Exception e) { System.out.println("發生異常"); } } }
在處理異常時,並不要求拋出的異常同 catch
所聲明的異常徹底匹配,子類的對象也能夠匹配父類的處理程序。好比異常 A 繼承於異常 B,那麼在處理多個異常時,必定要將異常 A 放在異常 B 以前捕獲,若是將異常 B 放在異常 A 以前,那麼將永遠匹配到異常 B,異常 A 將永遠不可能執行,而且編譯器將會報錯。
父類的異常捕獲語句不能夠寫在子類異常捕獲語句前面
自定義一個異常類很是簡單,只須要讓它繼承 Exception 或其子類就行。在自定義異常類的時候,建議同時提供無參構造方法和帶字符串參數的構造方法,後者能夠爲你在調試時提供更加詳細的信息。
在 Java
中你能夠自定義異常。編寫本身的異常類時須要記住下面的幾點。
Throwable
的子類。Exception
類。RuntimeException
類。public class Demo3 { public static void main(String[] args) { int number = 5; for(int i = 4; i > -1; i--) { if (i == 0) { throw new MyException("這是一個異常"); } System.out.println(number / i); } } } //自定義異常類 ,繼承於ArithmeticException class MyException extends ArithmeticException { //實現無參構造器 public MyException() { } //實現參數構造器,可將提示信息做爲異常結果輸出 public MyException(String msg) { super(msg); } }
當異常拋出後,咱們能夠經過異常堆棧追蹤程序的運行軌跡,以便咱們更好的 DEBUG
。
public class Demo4 { public static void method1() { method2(); } public static void method2() { throw new NullPointerException(); } public static void main(String[] args) { try{ method1(); } catch (Exception e) { // 打印堆棧軌跡 e.printStackTrace(); } } } 打印結果: java.lang.NullPointerException at Demo4.method2(Demo4.java:10) at Demo4.method1(Demo4.java:6) at Demo4.main(Demo4.java:15)
經過上面的異常堆棧軌跡,在對比咱們方法的調用過程,能夠得出異常信息中首先打印的是距離拋出異常最近的語句,接着是調用該方法的方法,一直到最開始被調用的方法。 從下往上看 ,就能夠得出程序運行的軌跡。
try
異常的捕獲、拋出和異常處理是維持代碼健壯性的重要條件。靈活使用異常及處理,不只能最大限度的避免出錯,也能增長軟件的容錯機制。
相關代碼記錄於GitHub中,歡迎各位夥伴 Star !
有任何疑問 微信搜一搜 [程序猿大博] 與我聯繫~
若是以爲對您有所幫助,請 點贊 ,收藏 ,若有不足,請評論或私信指正!謝謝~