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塊無論異常是否發生,只要對應的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塊。
首先一個不容易理解的事實:在 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中拋出的異常
自定義異常
自定義異常能夠按照如上圖方式,定義一個父類業務異常繼承自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;
}
}
複製代碼