您好,登錄后才能下訂單哦!
本文實例講述了java的異常與處理機制。分享給大家供大家參考,具體如下:
java的異常機制
Throwable類
Throwable類是Java異常類型的頂層父類,一個對象只有是 Throwable 類的(直接或者間接)實例,他才是一個異常對象,才能被異常處理機制識別。JDK中內建了一些常用的異常類,我們也可以自定義異常。
Throwable又派生出Error類和Exception類。
錯誤:Error類以及他的子類的實例,代表了JVM本身的錯誤。錯誤不能被程序員通過代碼處理,Error很少出現。因此,程序員應該關注Exception為父類的分支下的各種異常類。
異常:Exception以及他的子類,代表程序運行時發送的各種不期望發生的事件。可以被Java異常處理機制使用,是異常處理的核心。
java異常體系結構
Java中的異常分為兩大類(根據javac對異常的處理要求):
Checked exception(受檢異常):除了Error 和 RuntimeException的其它異常。受檢異常表示程序本身沒有問題,但由于I/O、網絡、數據庫等其他不可預測的錯誤導致的異常,也可能是因為資源耗盡導致的異常。javac強制要求程序員為這樣的異常做預備處理工作(使用try…catch…finally或者throws)。在方法中要么用try-catch語句捕獲它并處理,要么用throws子句聲明拋出它,否則編譯不會通過。這樣的異常一般是由程序的運行環境導致的。因為程序可能被運行在各種未知的環境下,而程序員無法干預用戶如何使用他編寫的程序,于是程序員就應該為這樣的異常時刻準備著。如SQLException , IOException,ClassNotFoundException 等。
Unchecked exception(Runtime Exception)(未受檢異常):Error 和 RuntimeException 以及他們的子類。未受檢異常一般認為是代碼的邏輯問題,一般需要修改代碼來解決異常,也可以使用異常機制處理。這樣的異常發生的原因多半是代碼寫的有問題。如除0錯誤ArithmeticException,錯誤的強制類型轉換錯誤ClassCastException,數組索引越界ArrayIndexOutOfBoundsException,使用了空對象NullPointerException等等。
Runtime Exception類直接繼承自Exception類,Java中所有的運行時異常都會直接或間接地繼承自Runtime Exception
Java中凡是繼承自Exception,而不是繼承自Runtime Exception類的異常都是Checked Exception
異常處理的基本語法
在編寫代碼處理異常時,對于檢查異常,有2種不同的處理方式:使用try…catch…finally語句塊處理它。或者,在函數簽名中使用throws 聲明交給函數調用者caller去解決。
(1)try…catch…finally語句塊
try{ //try塊中放可能發生異常的代碼。 //如果執行完try且不發生異常,則接著去執行finally塊和finally后面的代碼(如果有的話)。 //如果發生異常,則嘗試去匹配catch塊。 }catch(SQLException SQLexception){ //每一個catch塊用于捕獲并處理一個特定的異常,或者這異常類型的子類。Java7中可以將多個異常聲明在一個catch中。 //catch后面的括號定義了異常類型和異常參數。如果異常與之匹配且是最先匹配到的,則虛擬機將使用這個catch塊來處理異常。 //在catch塊中可以使用這個塊的異常參數來獲取異常的相關信息。異常參數是這個catch塊中的局部變量,其它塊不能訪問。 //如果當前try塊中發生的異常在后續的所有catch中都沒捕獲到,則先去執行finally,然后到這個函數的外部caller中去匹配異常處理器。 //如果try中沒有發生異常,則所有的catch塊將被忽略。 }catch(Exception exception){ //... }finally{ //finally塊通常是可選的。 //無論異常是否發生,異常是否匹配被處理,finally都會執行。 //一個try至少要有一個catch塊,否則, 至少要有1個finally塊。但是finally不是用來處理異常的,finally不會捕獲異常。 //如果在try或者catch語句中存在return語句,則return語句會在finally語句執行結束后執行,但是finally并不能改變返回值。 //如果在finally語句中也有return,那么try和catch中的return語句會丟失,實際會返回finally中的返回值。 //finally主要做一些清理工作,如流的關閉,數據庫連接的關閉等。 }
注意點:
try塊中的局部變量和catch塊中的局部變量(包括異常變量),以及finally中的局部變量,他們之間不可共享使用。
每一個catch塊用于處理一個異常。異常匹配是按照catch塊的順序從上往下尋找的,只有第一個匹配的catch會得到執行。匹配時,不僅運行精確匹配,也支持父類匹配,因此,如果同一個try塊下的多個catch異常類型有父子關系,應該將子類異常放在前面,父類異常放在后面,這樣保證每個catch塊都有存在的意義。
finally塊不管異常是否發生,只要對應的try執行了,則它一定也執行。只有一種方法讓finally塊不執行:System.exit()。因此finally塊通常用來做資源釋放操作:關閉文件,關閉數據庫連接等等。良好的編程習慣是:在try塊中打開資源,在finally塊中清理釋放這些資源。
finally塊沒有處理異常的能力。處理異常的只能是catch塊。
在同一try…catch…finally塊中 ,如果try中拋出異常,且有匹配的catch塊,則先執行catch塊,再執行finally塊。如果沒有catch塊匹配,則先執行finally,然后去外面的調用者中尋找合適的catch塊。
在同一try…catch…finally塊中 ,try發生異常,且匹配的catch塊中處理異常時也拋出異常,那么后面的finally也會執行:首先執行finally塊,然后去外圍調用者中尋找合適的catch塊。
(2)throws 函數聲明
throws聲明:如果一個方法內部的代碼會拋出檢查異常(checked exception),而方法自己又沒有完全處理掉,則javac保證你必須在方法的簽名上使用throws關鍵字聲明這些可能拋出的異常,否則編譯不通過。
throws是另一種處理異常的方式,它不同于try…catch…finally,throws僅僅是將函數中可能出現的異常向調用者聲明,而自己則不具體處理。
采取這種異常處理的原因可能是:方法本身不知道如何處理這樣的異常,或者說讓調用者處理更好,調用者需要為可能發生的異常負責。
public void foo() throws ExceptionType1 , ExceptionType2 ,ExceptionTypeN { //foo內部可以拋出 ExceptionType1 , ExceptionType2 ,ExceptionTypeN 類的異常,或者他們的子類的異常對象。 }
throw 異常拋出語句
語法 : throw exceptionObject
程序員也可以通過throw語句手動顯式的拋出一個異常。throw語句的后面必須是一個異常對象。
在某個方法(如:a方法)中,使用throw new 異常,的方式拋出異常異常,即本方法不會對異常進行處理,而是由調用a 的方法b來處理(此時b會使用throws關鍵字拋出),如果b也被方法c調用,那么c來處理,逐層類推,直到main方法,如果main方法也是選擇拋出異常,那么就叫交給JVM處理
throw 語句必須寫在函數中,執行throw 語句的地方就是一個異常拋出點,它和由JRE自動形成的異常拋出點沒有任何差別。
package practice; public class ExceptionTest { public static void test(Object obj) { try { if (obj == null) { throw new Exception();// 此處拋出的異常,在catch中被處理了 } } catch (Exception e) { System.out.println("nullpoint"); } } public static void test2(Object obj) throws Exception { try { obj.toString(); } catch (Exception e) { throw new Exception();//在catch塊中拋出新的異常,構成了異常鏈,這是因為原來的異常對象e可能不能處理這個異常,需要另一個異常對象來處理該異常 } } public static void test1(Object obj) throws Exception { if (obj == null) { throw new Exception();// 此處拋出的異常,通過throws的方式,由調用test的方法處理 } } public static void main(String[] args) throws Exception{ ExceptionTest.test(null); //處理拋出異常的兩種方式 //方式一:test2函數使用throws拋出了異常,所以得接住這個異常,并處理 try { ExceptionTest.test2(null); }catch(Exception e) { System.out.println("nullpoint"); } //方式二:test1拋出的異常使用Throws的方式處理 ExceptionTest.test1(null); } }
自定義異常
自定義異常:通常就是定義了一個繼承自Exception類的子類,那么這個類就是一個自定義異常類。通常情況下,我們都會直接繼承自Exception類,一般不會繼承某個運行時的異常類
異常的特性:
一個try可以有多個catch塊,但運行時只有一個catch塊可以被執行,并且是按照順序來尋找匹配的catch塊的,所以需要將父類的異常需要放在后面的catch塊中
try{ test.method(str); }catch (MyException e) { System.out.println("MyException catch"); e.printStackTrace(); }catch(MyException2 e) { System.out.println("MyException2 catch"); e.printStackTrace(); }catch(Exception e) { System.out.println(“Exception catch”); e.printStackTrace(); } finally {System.out.println("finally"); }
try{ test.method(str); }catch(Exception e) { System.out.println(“Exception catch”); e.printStackTrace(); } catch (MyException e) { System.out.println("MyException catch"); e.printStackTrace(); }catch(MyException2 e) { System.out.println("MyException2 catch"); e.printStackTrace(); } finally {System.out.println("finally"); }
面試題目
題目一:
package defineexception; public class ExceptionTest3 { public void method() { try { System.out.println("try"); return; } catch(Exception ex) { System.out.println("異常發生了"); } finally { System.out.println("finally"); } System.out.println("異常處理后續的代碼"); } public static void main(String[] args) { ExceptionTest3 test =new ExceptionTest3(); test.method(); } }
結果:
try
finally
分析
try塊中存在return語句,那么首先也需要將finally塊中的代碼執行完畢,再執行return語句,而且之后的其他代碼也不會再執行了
題目二:
package defineexception; public class ExceptionTest3 { public void method() { try { System.out.println("try"); System.exit(0); } catch(Exception ex) { System.out.println("異常發生了"); } finally { System.out.println("finally"); } System.out.println("異常處理后續的代碼"); } public static void main(String[] args) { ExceptionTest3 test =new ExceptionTest3(); test.method(); } }
結果
try
分析
先執行try塊中的System.exit(0)
語句,已經退出了虛擬機系統,所以不會執行finally
塊的代碼
參考鏈接
https://www.jb51.net/article/161574.htm
更多java相關內容感興趣的讀者可查看本站專題:《Java面向對象程序設計入門與進階教程》、《Java數據結構與算法教程》、《Java操作DOM節點技巧總結》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對大家java程序設計有所幫助。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。