天天看點

解析Java-throw抛出異常詳細過程

作者:華為雲開發者聯盟

本文分享自華為雲社群《Java-throw異常詳解以及過程-雲社群-華為雲》,作者:gentle_zhou。

首先,我們知道Java有3種抛出異常的形式:throw(執行的時候一定抛出某種異常對象), throws(出現異常的可能性,不一定會發生), 系統自動抛異常。

throw用在一個語句抛出異常的時候,throw (an instance of exception class)比如一個方法/函數裡,try{…}catch(Exception e){throw new ArithmeticException(“XXX”);}finally{…};

throws則是用在聲明方法可能抛出異常的時候,throw (exception class)比如public int division(int x, int y) throws ArithmeticException {…};

系統自動抛異常則是當程式語句出現邏輯錯誤,主義錯誤或類型轉換錯誤的時候,系統自動抛出異常,比如int a = 5; int b = 0; c = a/b; 這個時候移動會自動抛出ArithmeticException。

什麼是異常

異常,顧名思義,就是有異于正常狀态,有錯誤發生。而這錯誤會阻止Java目前函數方法的運作。

那麼Java裡面異常的體系是怎麼樣的呢?

1.Java裡面所有不正常類都繼承于Throwable類;而Throwable類包括2類:Error類和Exception類。

2.Error類包括虛拟機錯誤(VirtualMachineError)和線程死鎖(ThreadDeath)。

3.Exception類則是我們在說的異常;包括運作時異常(RuntimeException)和檢查異常;這裡的異常通常是編碼,環境,使用者操作輸入出現了問題。

4.運作時異常(RuntimeException)包括以下4種異常:空指針異常(NullPointerException),數組下标越界異常(ArrayIndexOutOfBoundsException),類型轉換異常(ClassCastException),算術異常(ArithmeticException)。

空指針異常:

解析Java-throw抛出異常詳細過程
解析Java-throw抛出異常詳細過程

數組下标越界異常:

解析Java-throw抛出異常詳細過程
解析Java-throw抛出異常詳細過程

類型轉換異常:

解析Java-throw抛出異常詳細過程
解析Java-throw抛出異常詳細過程

算術異常:

解析Java-throw抛出異常詳細過程
解析Java-throw抛出異常詳細過程

5.最後剩下的檢查異常則是剩下各種異常的集合;這裡發生異常的原因有很多,檔案異常(IOException),連接配接異常(SQLException)等等;和運作時異常不同的是,這裡的異常我們必須手動在代碼裡添加try…catch…(finally…)語句來捕獲處理。

今天又了解學習到了一些具體的額外的異常:

解析Java-throw抛出異常詳細過程

Throw抛出異常詳細過程

和throws聲明方法可能會發生異常不同,throw語句則是直接抛出一個異常。

前面有提到,throw (an instance of exception class),這裡的一個exception類的執行個體其實也可以說是一個ExceptionObject(Throwable類或則其子類 的對象;也可以是自定義的繼承自Throwable的直接或間接的異常類)。如果,我們用了throw new String(“異常XXX”); 則會在編譯的時候報錯,因為String 類并不是Throwable類的子類。

接着讓我們回到怎麼用throw語句的階段。

一般我們有兩種方式來用throw:直接在某處會發生異常的地方用throw語句或則用try…catch…finally…語句來捕獲處理異常和關閉釋放資源。

首先是第一種,直接在某處會發生異常的地方用throw語句;這是一種主動的方法,主動抛出異常去處理。

而第二種,用try…catch…finally…語句來捕獲處理異常和關閉釋放資源 則是被動的方法。try裡面放入可能會發生異常的語句塊,如果在運作期間遇到了異常,則會交給catch來處理異常(catch可以是多個,處理不同的異常),finally則是無論有沒有異常發生,隻要加上了就會運作。

首先我們來看第一種方法的函數:

解析Java-throw抛出異常詳細過程

我們的int c = 4/2,其實是正确的;但是我們的throw 語句主動抛出了異常,那麼程式就會到catch裡面找有沒有這個異常,有的話進行處理。是以我們要主動抛異常的話,要很确信這個代碼一定會發生異常且後期不太會去變動了(最好放在if條件語句裡)。是以我們得到的結果如下:

解析Java-throw抛出異常詳細過程

接着我們來看第二種方法。我們一開始先測正确的,隻是把主動抛出異常語句給注釋掉:

解析Java-throw抛出異常詳細過程

因為try裡面的語句塊沒有異常,是以隻執行了try和finally裡面的語句塊。運作的結果如下:

解析Java-throw抛出異常詳細過程

我們接着來測當try裡面的語句塊有異常,且沒有主動抛出異常的時候,try會不會捕捉到異常吧:

解析Java-throw抛出異常詳細過程

得到的結果如下,會去處理異常和執行finally裡面的語句塊:

解析Java-throw抛出異常詳細過程

最後深入了解一點try裡面的異常觸發會逐層向上的這個概念。在我們try語句裡主動/被動抛出異常的時候,程式會調向調用者程式(上面的例子裡就是我們自己這個函數;但有的時候我們會在try語句裡執行别的函數比如B,這個函數B裡我們假如觸發了異常,它會調向try語句所在的函數A),尋找和它相比對的catch語句,執行catch語句裡面相應的異常處理程式;但假如沒有找到相比對的catch語句,那麼它會再轉向上一層的調用程式…這樣逐層向上,直到最外層的異常程式終止程式并列印出stack trace。

參考資料

  1. rollbar.com/guides/java…
  2. www.javatpoint.com/throw-keywo…
  3. www.geeksforgeeks.org/throw-throw…

點選下方,第一時間了解華為雲新鮮技術~

華為雲部落格_大資料部落格_AI部落格_雲計算部落格_開發者中心-華為雲

繼續閱讀