<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                [TOC] # 簡介 Java 標準庫內建了一些通用的異常,這些類以 Throwable 為頂層父類,Throwable 又派生出`Error`類和`Exception`類: * **Error(錯誤):**Error 類以及他的子類的實例,一般標識 JVM 本身的錯誤。錯誤不能被程序員通過代碼處理,Error 很少出現。因此,程序員應該關注Exception為父類的分支下的各種異常類。 * **Exception(異常):**Exception 以及他的子類,代表程序運行時發送的各種不期望發生的事件。可以被 Java 異常處理機制使用,是異常處理的核心。 根據 JAVAC 對項目在編譯時是否進行檢查又可以分為 unckecked exception(非檢查異常)與 checked exception(檢查異常): * **Unckecked Exception(非檢查異常):**Error 和 RuntimeException 以及他們的子類在編譯時,發現與提醒存在異常信息,所以也就不會發現與處理這些異常。對于這些異常發生的原因多半是代碼寫的有問題導致,一般我們應該修正代碼,而不是去通過異常處理器處理。 * **Checked Exception(檢查異常):**除了 Error 和 RuntimeException 之外的其它異常,JAVAC 強制要求開發人員提前預備處理異常工作,如使用`try-catch`,`finally`或者`throws`,在方法中要么用 try-catch 捕獲并處理異常,要么用 throws 聲明拋出交給上級處理,否則編譯將不會通過。這樣的異常一般是由開發人員的運行環境引起的,因為程序可能被運行在各種未知的環境下,而開發人員無法干預用戶如何使用他編寫的程序,于是開發人員就應該提前考慮到可能發生的異常信息并處理。 **非檢查異常如:** * ArithmeticException * ClassCastException * ArrayIndexOutOfBoundsException * NullPointerException **檢查異常如:** * SQLException * IOException * ClassNotFoundException # 異常類結構圖 ![](https://img.kancloud.cn/16/d3/16d3e4b366b0c6cb5a6a0fc9a67c717e_636x395.png) # 異常關鍵字 * **try:**try 代碼塊中放可能發生異常的代碼,當發生異常時候會調用后面的 catch 處理異常。 * **catch:**當 try 代碼塊中的代碼出現異常時,按代碼順序依次和多個 catch 中設置的異常類型進行檢測,如果類型匹配就進行異常處理。 * **throw:**用來在方法中使用其拋出指定的異常對象,當拋出異常時會檢查該代碼中是否有處理異常邏輯,有處理即按照處理邏輯運行,未處理時程序將拋出異常信息,然后程序終止。 * **throws:**用在方法頭部中聲明拋出多個異常,調用方法會提醒處理異常,不處理即不能通過編譯。 * **finally:**不管異常是否出現都會執行 finally 代碼塊中的內容,這個代碼塊中主要做一些清理資源的工作,如流的關閉,數據庫連接的關閉等,不推薦用于 return 返回信息。 # 異常的繼承體系 在Java中使用Exception類來描述異常 ![](https://box.kancloud.cn/d91f6bb6148147defaaaa79e00288cc6_930x100.png) 我們可以發現Exception有繼承關系,它的父類是Throwable。Throwable是Java 語言中所有錯誤或異常的超類 ![](https://box.kancloud.cn/bc76656c5087f0ba6328005e1185d0f1_916x361.png) 另外,在異常Exception類中,有一個子類要特殊說明一下,RuntimeException子類,RuntimeException及其它的子類只能在Java程序運行過程中出現 異常繼承體系總結: ~~~ Throwable: 它是所有錯誤與異常的超類(祖宗類) |- Error 錯誤,不能處理只能避免 |- Exception 編譯期異常,進行編譯JAVA程序時出現的問題 |- RuntimeException 運行期異常, JAVA程序運行過程中出現的問題 ~~~ # 拋出異常throw 在java中,提供了一個throw關鍵字,它用來拋出一個指定的異常對象。那么,拋出一個異常具體如何操作呢? 1. 創建一個異常對象。封裝一些提示信息(信息可以自己編寫)。 2. 需要將這個異常對象告知給調用者。怎么告知呢?怎么將這個異常對象傳遞到調用者處呢?通過關鍵字throw就可以完成。throw 異常對象; throw用在方法內,用來拋出一個異常對象,將這個異常對象傳遞到調用者處,并結束當前方法的執行。 使用格式: ~~~ throw new 異常類名(參數); ~~~ 例如: ~~~ throw new NullPointerException("要訪問的arr數組不存在"); throw new ArrayIndexOutOfBoundsException("該索引在數組中不存在,已超出范圍"); ~~~ 下面是異常類ArrayIndexOutOfBoundsException與NullPointerException的構造方法 ![](https://box.kancloud.cn/c75ee634dfb27bf41ce338f4d6ce76be_937x349.png) # 聲明異常throws 聲明:將問題標識出來,報告給調用者。如果方法內通過throw拋出了編譯時異常,而沒有捕獲處理(稍后講解該方式),那么必須通過throws進行聲明,讓調用者去處理。 聲明異常格式: ~~~ 修飾符 返回值類型 方法名(參數) throws 異常類名1,異常類名2… { } ~~~ ## throw與throws的比較 1. throws出現在方法函數頭;而throw出現在函數體。 2. throws表示出現異常的一種可能性,并不一定會發生這些異常;throw則是拋出了異常,執行throw則一定拋出了某種異常對象。 # 捕獲異常`try…catch…finally` 捕獲:Java中對異常有針對性的語句進行捕獲,可以對出現的異常進行指定方式的處理 捕獲異常格式: ~~~ try { //需要被檢測的語句。 } catch(異常類 變量) { //參數。 //異常的處理語句。 } finally { //一定會被執行的語句。 } ~~~ try:該代碼塊中編寫可能產生異常的代碼。 catch:用來進行某種異常的捕獲,實現對捕獲到的異常進行處理。 finally:有一些特定的代碼無論異常是否發生,都需要執行。另外,因為異常會引發程序跳轉,導致有些語句執行不到。而finally就是解決這個問題的,在finally代碼塊中存放的代碼都是一定會被執行的。 # 運行時期異常 * RuntimeException和他的所有子類異常,都屬于運行時期異常。NullPointerException,ArrayIndexOutOfBoundsException等都屬于運行時期異常. * 運行時期異常的特點: * 方法中拋出運行時期異常,方法定義中無需throws聲明,調用者也無需處理此異常 * 運行時期異常一旦發生,需要程序人員修改源代碼. # 異常在方法重寫中細節 * **子類覆蓋父類方法時,如果父類的方法聲明異常,子類只能聲明父類異常或者該異常的子類,或者不聲明。** 例如: ~~~ class Fu { public void method () throws RuntimeException { } } class Zi extends Fu { public void method() throws RuntimeException { } //拋出父類一樣的異常 //public void method() throws NullPointerException{ } //拋出父類子異常 } ~~~ * **當父類方法聲明多個異常時,子類覆蓋時只能聲明多個異常的子集。** 例如: ~~~ class Fu { public void method () throws NullPointerException, ClassCastException{ } } class Zi extends Fu { public void method()throws NullPointerException, ClassCastException { } public void method() throws NullPointerException{ } //拋出父類異常中的一部分 public void method() throws ClassCastException { } //拋出父類異常中的一部分 } ~~~ * **當被覆蓋的方法沒有異常聲明時,子類覆蓋時無法聲明異常的**。 例如: ~~~ class Fu { public void method (){ } } class Zi extends Fu { public void method() throws Exception { }//錯誤的方式 } ~~~ 舉例:父類中會存在下列這種情況,接口也有這種情況 問題:接口中沒有聲明異常,而實現的子類覆蓋方法時發生了異常,怎么辦? 答:無法進行throws聲明,只能catch的捕獲。萬一問題處理不了呢?catch中繼續throw拋出,但是只能將異常轉換成RuntimeException子類拋出 ~~~ interface Inter { public abstract void method(); } class Zi implements Inter { public void method(){ //無法聲明 throws Exception int[] arr = null; if (arr == null) { //只能捕獲處理 try{ throw new Exception(“哥們,你定義的數組arr是空的!”); } catch(Exception e){ System.out.println(“父方法中沒有異常拋出,子類中不能拋出Exception異常”); //我們把異常對象e,采用RuntimeException異常方式拋出 throw new RuntimeException(e); } } } } ~~~ # 異常中常用方法 在Throwable類中為我們提供了很多操作異常對象的方法,常用的如下 ![](https://box.kancloud.cn/351530123f49a8710dd36698718603e5_919x279.png) * getMessage方法:返回該異常的詳細信息字符串,即異常提示信息 * toString方法:返回該異常的名稱與詳細信息字符串 * printStackTrace:在控制臺輸出該異常的名稱與詳細信息字符串、異常出現的代碼位置 ~~~ try { Person p= null; if (p==null) { throw new NullPointerException(“出現空指針異常了,請檢查對象是否為null”); } } catch (NullPointerException e) { String message = e.getMesage(); System.out.println(message ); String result = e.toString(); System.out.println(result); e.printStackTrace(); } ~~~ # 自定義異常 **java中所有的異常類,都是繼承Throwable,或者繼承Throwable的子類。這樣該異常才可以被throw拋出。** **說明這個異常體系具備一個特有的特性:可拋性:即可以被throw關鍵字操作。** 并且查閱異常子類源碼,發現每個異常中都調用了父類的構造方法,把異常描述信息傳遞給了父類,讓父類幫我們進行異常信息的封裝。 例如NullPointerException異常類源代碼: ~~~ public class NullPointerException extends RuntimeException { public NullPointerException() { super();//調用父類構造方法 } public NullPointerException(String s) { super(s);//調用父類具有異常信息的構造方法 } } ~~~ * 自定義異常繼承Exception演示 ~~~ class MyException extends Exception{ /* 為什么要定義構造函數,因為看到Java中的異常描述類中有提供對異常對象的初始化方法。 */ public MyException(){ super(); } public MyException(String message) { super(message);// 如果自定義異常需要異常信息,可以通過調用父類的帶有字符串參數的構造函數即可。 } } ~~~ * 自定義異常繼承RuntimeException演示 ~~~ class MyException extends RuntimeException{ /* 為什么要定義構造函數,因為看到Java中的異常描述類中有提供對異常對象的初始化方法。 */ MyException(){ super(); } MyException(String message) { super(message);// 如果自定義異常需要異常信息,可以通過調用父類的帶有字符串參數的構造函數即可。 } } ~~~ # assert斷言 程序執行到某行代碼處一定是預期的結果 默認情況下斷言不應該影響程序的運行,也就是說在java解釋程序的運行時候斷言不起作用 啟用斷言: `java -ea TestDemo` ~~~ int num = 20; assert num == 10: "num不是10"; ~~~ java的斷言設計要比c++強很多,它不會影響程序的執行 # try-with-resource關閉資源 JDK1.7中 ## 簡介 我們知道,在Java編程過程中,如果打開了外部資源(文件、數據庫連接、網絡連接等),我們必須在這些外部資源使用完畢后,手動關閉它們。因為外部資源不由JVM管理,無法享用JVM的垃圾回收機制,如果我們不在編程時確保在正確的時機關閉外部資源,就會導致外部資源泄露,緊接著就會出現文件被異常占用,數據庫連接過多導致連接池溢出等諸多很嚴重的問題。 ## 傳統的資源關閉方式 為了確保外部資源一定要被關閉,通常關閉代碼被寫入finally代碼塊中,當然我們還必須注意到關閉資源時可能拋出的異常,于是變有了下面的經典代碼: ~~~ public static void main(String[] args) { FileInputStream inputStream = null; try { inputStream = new FileInputStream(new File("test")); System.out.println(inputStream.read()); } catch (IOException e) { throw new RuntimeException(e.getMessage(), e); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { throw new RuntimeException(e.getMessage(), e); } } } } ~~~ 熟悉其他語言的朋友可能會開始吐槽了,在C++中,我們可以把關閉資源的代碼放在析構函數中,在C#中,我們有using代碼塊。這些語法都有一個共同的特性,讓外部資源的關閉行為與外部資源的句柄對象的生命周期關聯,當外部資源的句柄對象生命周期終結時(例如句柄對象已出作用域),外部資源的關閉行為將被自動調用。這樣不僅更加符合面向對象的編程理念(將關閉外部資源的行為內聚在外部資源的句柄對象中),也讓代碼更加簡潔易懂。怎么到了Java這里,就找不到自動關閉外部資源的語法特性了呢。 ## try-with-resource語法 確實,在JDK7以前,Java沒有自動關閉外部資源的語法特性,直到JDK7中新增了try-with-resource語法,才實現了這一功能。 那什么是try-with-resource呢?簡而言之,當一個外部資源的句柄對象(比如FileInputStream對象)實現了AutoCloseable接口,那么就可以將上面的板式代碼簡化為如下形式: ~~~ public static void main(String[] args) { try (FileInputStream inputStream = new FileInputStream(new File("test"))) { System.out.println(inputStream.read()); } catch (IOException e) { throw new RuntimeException(e.getMessage(), e); } } ~~~ 將外部資源的句柄對象的創建放在try關鍵字后面的括號中,當這個try-catch代碼塊執行完畢后,Java會確保外部資源的close方法被調用。代碼是不是瞬間簡潔許多! ## 實現原理 try-with-resource并不是JVM虛擬機的新增功能,只是JDK實現了一個語法糖,當你將上面代碼反編譯后會發現,其實對JVM虛擬機而言,它看到的依然是之前的寫法: ~~~ public static void main(String[] args) { try { FileInputStream inputStream = new FileInputStream(new File("test")); Throwable var2 = null; try { System.out.println(inputStream.read()); } catch (Throwable var12) { var2 = var12; throw var12; } finally { if (inputStream != null) { if (var2 != null) { try { inputStream.close(); } catch (Throwable var11) { var2.addSuppressed(var11); } } else { inputStream.close(); } } } } catch (IOException var14) { throw new RuntimeException(var14.getMessage(), var14); } } ~~~ ## 異常抑制 通過反編譯的代碼,大家可能注意到代碼中有一處對異常的特殊處理: ~~~ var2.addSuppressed(var11); ~~~ 這是try-with-resource語法涉及的另外一個知識點,叫做異常抑制。當對外部資源進行處理(例如讀或寫)時,如果遭遇了異常,且在隨后的關閉外部資源過程中,又遭遇了異常,那么你catch到的將會是對外部資源進行處理時遭遇的異常,關閉資源時遭遇的異常將被“抑制”但不是丟棄,通過異常的getSuppressed方法,可以提取出被抑制的異常。 ## 總結 1. **當一個外部資源的句柄對象實現了AutoCloseable接口或者他的子接口Closeable,JDK7中便可以利用try-with-resource語法更優雅的關閉資源,消除板式代碼** 2. try-with-resource時,如果對外部資源的處理和對外部資源的關閉均遭遇了異常,“關閉異常”將被抑制,“處理異常”將被拋出,但“關閉異常”并沒有丟失,而是存放在“處理異常”的被抑制的異常列表 3. 可以在一條try語句中管理多個資源,每個資源以`";"`隔離開來 ## jdk9改進 現在用資源語句編寫 try 將更容易。 以前,執行后必須關閉的所有資源必須在 try 子句中初 始化,如下例所示: 從 Java 9 開始,我們可以在 try 子句中使用最終和有效的最終資源: ~~~ Resource res1 = new Resource(); Resource res2 = new Resource(); try (res1; res2) { } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看