java異常機制

Java異常的分類和類結構圖

Java標準庫內建了一些通用的異常,這些類以Throwable爲頂層父類。Throwable又派生出Error類和Exception類。錯誤:Error類以及他的子類的實例,表明了JVM自己的錯誤。錯誤不能被程序員經過代碼處理,Error不多出現。所以,程序員應該關注Exception爲父類的分支下的各類異常類。異常:Exception以及他的子類,表明程序運行時發送的各類不指望發生的事件。能夠被Java異常處理機制使用,是異常處理的核心。html

整體上咱們根據Javac對異常的處理要求,將異常類分爲2類。java

非檢查異常(unckecked exception):Error 和 RuntimeException 以及他們的子類。javac在編譯時,不會提示和發現這樣的異常,不要求在程序處理這些異常。因此若是願意,咱們能夠編寫代碼處理(使用try…catch…finally)這樣的異常,也能夠不處理。對於這些異常,咱們應該修正代碼,而不是去經過異常處理器處理 。這樣的異常發生的緣由多半是代碼寫的有問題。如除0錯誤ArithmeticException,錯誤的強制類型轉換錯誤ClassCastException,數組索引越界ArrayIndexOutOfBoundsException,使用了空對象NullPointerException等等。程序員

檢查異常(checked exception):除了Error 和 RuntimeException的其它異常。javac強制要求程序員爲這樣的異常作預備處理工做(使用try…catch…finally或者throws)。在方法中要麼用try-catch語句捕獲它並處理,要麼用throws子句聲明拋出它,不然編譯不會經過。這樣的異常通常是由程序的運行環境致使的。由於程序可能被運行在各類未知的環境下,而程序員沒法干預用戶如何使用他編寫的程序,因而程序員就應該爲這樣的異常時刻準備着。如SQLException , IOException,ClassNotFoundException 等。數據庫

注意:檢查異常是在編譯時必須進行處理的異常,不然編譯不會經過,要求強制進行處理。非檢查異常(Runtime Exception)是運行時纔會出現的異常,不須要在程序中作強制處理。非檢查異常能夠不作處理,即不要求在程序中用try  catch捕獲或者用throws本身拋出。編程

異常處理的基本語法

在編寫代碼處理異常時,對於檢查異常,有2種不一樣的處理方式:使用try…catch…finally語句塊處理它。或者,在函數簽名中使用throws 聲明交給函數調用者caller去解決。數組

try…catch…finally語句塊bash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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不會捕獲異常。
//finally主要作一些清理工做,如流的關閉,數據庫鏈接的關閉等。
}


finally塊

finally塊無論異常是否發生,只要對應的try執行了,則它必定也執行。只有一種方法讓finally塊不執行:System.exit()。所以finally塊一般用來作資源釋放操做:關閉文件,關閉數據庫鏈接等等。app

良好的編程習慣是:在try塊中打開資源,在finally塊中清理釋放這些資源。函數

須要注意的地方:this

一、finally塊沒有處理異常的能力。處理異常的只能是catch塊。

二、在同一try…catch…finally塊中 ,若是try中拋出異常,且有匹配的catch塊,則先執行catch塊,再執行finally塊。若是沒有catch塊匹配,則先執行finally,而後去外面的調用者中尋找合適的catch塊。

三、在同一try…catch…finally塊中 ,try發生異常,且匹配的catch塊中處理異常時也拋出異常,那麼後面的finally也會執行:首先執行finally塊,而後去外圍調用者中尋找合適的catch塊。

finally塊和return

首先一個不容易理解的事實:在 try塊中即使有return,break,continue等改變執行流的語句,finally也會執行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args)
{
int re = bar();
System.out.println(re);
}
private static int bar()
{
try {
return 5 ;
} finally {
System.out.println( "finally" );
}
}
/*輸出:
finally
*/


注意:try .. catch ..finally語句塊中至少有一個try,至少有一個catch或者finally。若是catch沒有捕獲到異常,會直接在finally中處理。

<1>finally中的return會覆蓋try或catch塊中的return返回值。

<2>若是在try中使用了return就不用執行catch中的語句,可是永遠會執行finally中的語句,若是try中無retrun語句,在catch中拋出異常,而finally中使用了retrun,則catch中的語句不會被執行。

<3>若是同時在catch和finally中拋出異常,finally中拋出的異常

  • 不要在fianlly中使用return。
  • 不要在finally中拋出異常。
  • 減輕finally的任務,不要在finally中作一些其它的事情,finally塊僅僅用來釋放資源是最合適的。
  • 將盡可能將全部的return寫在函數的最後面,而不是try … catch … finally中。

自定義異常

这里写图片描述

自定義異常能夠按照如上圖方式,定義一個父類業務異常繼承自RuntimeException,子類異常繼承自父類,父類異常中定義code,message,date屬性。

RuntimeException源碼:

public class RuntimeException extends Exception {
    static final long serialVersionUID = -7034897190745766939L;

    /** Constructs a new runtime exception with {@code null} as its
     * detail message.  The cause is not initialized, and may subsequently be
     * initialized by a call to {@link #initCause}.
     */
    public RuntimeException() {
        super();
    }

    /** Constructs a new runtime exception with the specified detail message.
     * The cause is not initialized, and may subsequently be initialized by a
     * call to {@link #initCause}.
     *
     * @param   message   the detail message. The detail message is saved for
     *          later retrieval by the {@link #getMessage()} method.
     */
    public RuntimeException(String message) {
        super(message);
    }

    /**
     * Constructs a new runtime exception with the specified detail message and
     * cause.  <p>Note that the detail message associated with
     * {@code cause} is <i>not</i> automatically incorporated in
     * this runtime exception's detail message. * * @param message the detail message (which is saved for later retrieval * by the {@link #getMessage()} method). * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A <tt>null</tt> value is * permitted, and indicates that the cause is nonexistent or * unknown.) * @since 1.4 */ public RuntimeException(String message, Throwable cause) { super(message, cause); } /** Constructs a new runtime exception with the specified cause and a * detail message of <tt>(cause==null ? null : cause.toString())</tt> * (which typically contains the class and detail message of * <tt>cause</tt>). This constructor is useful for runtime exceptions * that are little more than wrappers for other throwables. * * @param cause the cause (which is saved for later retrieval by the * {@link #getCause()} method). (A <tt>null</tt> value is * permitted, and indicates that the cause is nonexistent or * unknown.) * @since 1.4 */ public RuntimeException(Throwable cause) { super(cause); } /** * Constructs a new runtime exception with the specified detail * message, cause, suppression enabled or disabled, and writable * stack trace enabled or disabled. * * @param message the detail message. * @param cause the cause. (A {@code null} value is permitted, * and indicates that the cause is nonexistent or unknown.) * @param enableSuppression whether or not suppression is enabled * or disabled * @param writableStackTrace whether or not the stack trace should * be writable * * @since 1.7 */ protected RuntimeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } }複製代碼
public class BusinessException extends RuntimeException {

    /**
     * 業務信息編碼
     */
    private String code;

   /**
     * 業務信息編碼
     */
    private String errorMessage;

    public BusinessException(String errorMessage) {
        super(errorMessage);//調用父類帶參構造函數,必須調用給Throwable超類中的message賦值,不然經過e.getMessage將取不到值
        this.errorMessage = errorMessage;
    }


}
複製代碼
相關文章
相關標籤/搜索