Java基礎——異常處理

  在程序運行過程當中,若是JVM檢測出一個不可能執行的操做,就會出現運行時錯誤。java

  在Java中,運行時錯誤會做爲異常拋出。異常就是一個對象,表示阻止正常進行程序執行的錯誤或者狀況。若是異常沒有被處理,那麼程序將會非正常終止。程序員


  異常是從方法拋出的。方法的調用者能夠捕獲以及處理該異常。編程

  throw語句的執行稱爲拋出一個異常。異常就是一個從異常類建立的對象。數組

  當異常被拋出時,正常的執行流程就被中斷。就像它的名字所提示的,「拋出異常」就是將異常從一個地方傳遞到另外一個地方。調用方法的語句包含在一個try塊和一個catch塊中。spa

  throw語句相似於方法調用,但不一樣於調用方法的是,它調用的是catch塊。從某種意義上講,catch塊就像帶參數的方法定義,這些參數匹配拋出的值的類型。可是,它不像方法,在執行完catch塊以後,程序控制再也不返回到throw語句;而是執行catch塊後的下一條語句。設計

  一個異常多是經過try塊中的throw語句直接拋出的,或者調用一個可能會拋出異常的方法而拋出。code

  使用異常處理的優勢:它能使方法拋出一個異常給它的調用者,並由調用者處理該異常。若是沒有這個能力,那麼被調用方法就必須本身處理異常或者終止該程序。被調用的方法一般不知道在出錯的狀況下該作什麼,這是庫方法的通常狀況。庫方法能夠檢測出錯誤,可是隻有調用者才知道出現錯誤時須要作些什麼。異常處理最根本的優點就是將檢測錯誤(由被調用的方法完成)從處理錯誤(由調用方法完成)中分離出來。orm


  異常時對象,而對象都採用類來定義。異常的根類是java.lang.Throwable。對象

  Java API中有不少預約義的異常類。blog

        

  Throwable類是全部異常類的根類。全部的Java異常類都直接或者間接地繼承自Throwable。能夠經過繼承Exception或者Exception的子類來建立本身的異常類。

  這些異常類能夠分爲三種主要類型:系統錯誤、異常和運行時異常。

  系統錯誤是由Java虛擬機拋出的,用Error類表示。Error類描述的是內部系統錯誤。這樣的錯誤不多發生。若是發生了,除了通知用戶以及儘可能穩妥地終止程序外,幾乎什麼也不能作。

  異常是用Exception類表示的,它描述的是由程序和外部環境所引發的錯誤,這些錯誤能被程序捕獲和處理。ClassNotFoundException、IOException

  運行時異常是用RuntimeException類表示的,它描述的是程序設計錯誤,例如,錯誤的類型轉換、訪問一個越界數組或數值錯誤。運行時異常一般是由Java虛擬機拋出的。ArithmeticException、NullPointerException、IndexOutOfBoundsException

  RuntimeException、Error以及它們的子類都稱爲免檢異常。全部其餘異常都稱爲必檢異常,意思是指編譯器會強制程序員檢查並經過try-catch塊處理它們,或者在方法頭進行聲明。

  在大多數狀況下,免檢異常都會反映出程序設計上不可恢復的邏輯錯誤。例如,若是經過一個引用變量訪問一個對象以前並未將一個對象賦值給它,就會拋出NullPointerException;若是訪問一個數組的越界元素,就會拋出IndexOutOfBoundsException異常,這些都是程序中必須糾正的邏輯錯誤。免檢異常可能在程序的任何一個地方出現。爲避免過多地使用try-catch塊,Java語言不強制要求編寫代碼捕獲或聲明免檢異常。


  異常的處理器是經過從當前的方法開始,沿着方法調用鏈,按照異常的反向傳播方向找到的。

  Java的異常處理模型基於三種操做:聲明一個異常、拋出一個異常和捕獲一個異常。

  聲明異常

  在Java中,當前執行的語句必屬於某個方法。Java解釋器調用main方法開始執行一個程序。每一個方法都必須聲明它可能拋出的必檢異常類型。這稱爲聲明異常。由於任何代碼均可能發生系統錯誤和運行時錯誤,所以,Java不要求在方法中顯示聲明Error和RuntimeException (免檢異常)。可是,方法要拋出的其餘異常都必須在方法頭中顯示聲明,這樣,方法的調用者會被告知有異常。

  若是方法沒有在父類中聲明異常,那麼就不能在子類中對其進行繼承來聲明異常。

  拋出異常

  檢測到錯誤的程序能夠建立一個適合的異常類型的實例並拋出它,這就稱爲拋出一個異常。

    IllegalArgumentException ex = new IllegalArgumentException ("Wrong Argument");

    throw ex;

    或者,根據偏好,也可使用下面的語句:

    throw new IllegalArgumentException (「Wrong Argument」);

  聲明異常的關鍵字是throws,拋出異常的關鍵字是throw。

  捕獲異常

  若是在執行try塊的過程當中沒有出現異常,則跳過catch子句。

  若是try塊中的某條語句拋出一個異常,Java就會跳過try塊中剩餘的語句,而後開始查找處理這個異常的代碼的過程。處理這個異常的代碼稱爲異常處理器;能夠從當前的方法開始,沿着方法調用鏈,按照異常的反向傳播方向找到這個處理器。從第一個到最後一個逐個檢查catch塊,判斷在catch塊中的異常類實例是不是該異常對象的類型。若是是,就將該異常對象賦給所聲明的變量,而後執行catch塊中的代碼。若是沒有發現異常處理器,Java會退出這個方法,把異常傳遞給調用這個方法的方法,繼續一樣的過程來查找處理器。若是在調用的方法鏈中找不處處理器,程序就會終止而且在控制檯上打印出錯信息。尋找處理器的過程稱爲捕獲一個異常。P393

  從一個通用的父類能夠派生出各類異常類。若是一個catch塊能夠捕獲一個父類的異常對象,它就能捕獲那個父類的全部子類的異常對象。

  在catch塊中異常被指定的順序是很是重要的。若是父類的catch塊出如今子類的catch以前,就會致使編譯錯誤。

  Java強迫程序員處理必檢異常,若是方法聲明瞭一個必檢異常(即Error或RuntimeException以外的異常),就必須在try-catch中調用它,或者在調用方法中聲明要拋出異常。

  從異常中獲取信息

  異常對象包含關於異常的有價值的信息。能夠利用下面這些java.lang.Throwable類中的實例方法獲取有關異常的信息。printStackTrace()方法在控制檯上打印棧跟蹤信息。getStackTrace()方法提供編程的方式,來訪問由printStackTrace()打印輸出的棧跟蹤信息。

  在異常事件中,執行仍然會繼續。若是處理器沒有捕獲到這個異常,程序就會忽然中斷。


finally子句

  不管異常是否產生,finally子句老是會被執行。

  有時候,不論異常是否出現或者是否被捕獲,都但願執行某些代碼。Java有一個finally子句,能夠用來達到這個目的。

  在任何狀況下,finally塊中的代碼都會執行,不論try塊中是否出現異常或者是否被捕獲。考慮下面三種可能的狀況:

  (1)若是try塊中沒有出現異常,執行finalStatements,而後執行try語句的下一條語句。

  (2)若是try塊中有一條語句引發異常,並被catch捕獲,而後跳過try塊的其餘語句,執行catch塊和finally子句。執行try語句以後的下一條語句。

  (3)若是try塊中有一條語句引發異常,可是沒有被任何catch塊捕獲,就會跳過try塊中的其餘語句,執行finally子句,而且將異常傳遞給這個方法的調用者。

  即便在到達finally塊以前有一個return語句,finally塊仍是會執行。


什麼時候使用異常

  當錯誤須要被方法的調用者處理的時候,方法應該拋出一個異常。

  try塊包含正常狀況下執行的代碼。catch塊包含異常狀況下執行的代碼。異常處理將處理錯誤的代碼從正常的程序設計任務中分離出來,這樣,可使程序更易讀、更易修改。可是,應該注意,因爲異常處理須要初始化新的異常對象,須要從調用棧返回,並且還須要沿着方法調用鏈來傳播異常(這裏注意方法調用的方向和異常傳播的方向是相反的)以便找到它的異常處理器,因此,異常處理一般須要更多的時間和資源。

  異常出如今方法中。若是想讓該方法的調用者處理異常,應該建立一個異常對象並將其拋出。若是能在發生異常的方法中處理異常,無須拋出異常。


從新拋出異常

  若是異常處理器不能處理一個異常,或者只是簡單地但願它的調用者注意到該異常,Java容許該異常的處理器從新拋出異常。

try{
    statements;
}
catch(TheException ex)
{
    perform operation before exits;
    throw ex;  
}

  語句throw ex從新拋出異常給調用者,以便調用者的其餘處理器得到處理異常ex的機會。


建立自定義異常

  能夠經過派生java.lang.Exception類來定義一個自定義異常類

  若是遇到一個不能用預約義異常恰當描述的問題,那就能夠經過派生Exception類或其子類,例如IOException,來建立本身的異常類。

相關文章
相關標籤/搜索