今天在看Zookeeper
源碼的時候發如今其源碼中使用到了UncaughtExceptionHandler
處理非檢查異常,關鍵是剛開始看的時候我不會呀!因此得學習呀!因此便出現了下文。java
這是一張Java異常體系大體圖:程序員
從大致上說,Java中的異常分爲兩種:數據庫
一、非檢查異常apache
非檢查異常爲Error
和RuntimeException
及其子類,javac
在編譯時,不會提示和發現這樣的異常,不要求在程序處理這些異常。因此若是願意,咱們能夠編寫代碼處理(使用try…catch…finally
)這樣的異常,也能夠不處理。對於這些異常,咱們應該修正代碼,而不是去經過異常處理器處理 。這樣的異常發生的緣由多半是代碼寫的有問題。如除0
錯誤ArithmeticException
,錯誤的強制類型轉換錯誤ClassCastException
,數組索引越界ArrayIndexOutOfBoundsException
,使用了空對象NullPointerException
等等數組
二、檢查異常bash
檢查異常則是除了Error
和 RuntimeException
的其它異常。javac強制要求程序員爲這樣的異常作預備處理工做(使用try…catch…finally
或者throws
)。在方法中要麼用try-catch語句捕獲它並處理,要麼用throws
子句聲明拋出它,不然編譯不會經過。這樣的異常通常是由程序的運行環境致使的。由於程序可能被運行在各類未知的環境下,而程序員沒法干預用戶如何使用他編寫的程序,因而程序員就應該爲這樣的異常時刻準備着。如SQLException
, IOException
,ClassNotFoundException
等。多線程
總結下:ide
try…catch…finally
塊捕獲異常爲何我要進行總結呢?下面我將說到!學習
不少時候咱們寫完代碼,運行以後總是會報空指針異常,咱們卻沒發現應該去捕獲它。特別是在多線程環境中,線程類Thread
的run()
方法是沒有拋出任何異常信息的,若是在run()
方法中報一個空指針異常,咱們卻沒有捕獲它,那後果將會是使線程中斷,線程中斷可能並非咱們想看到的結果。spa
最可氣的是,子線程拋出的異常信息,在其主線程一樣是捕獲不到的。下面舉例子演示下:
public class NoCaughtThread {
public static void main(String[] args) {
// 捕獲不到
try {
Thread thread = new Thread(new Task());
thread.start();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Task implements Runnable {
@Override
public void run() {
throw new NullPointerException();
}
}
複製代碼
程序運行結果:
Exception in thread "Thread-0" java.lang.NullPointerException
at org.apache.zookeeper.server.quorum.Task.run(NoCaughtThread.java:21)
at java.lang.Thread.run(Unknown Source)
複製代碼
爲了處理這些未捕獲的異常,jdk自帶了UncaughtExceptionHandler
類進行處理,實例以下:
import java.lang.Thread.UncaughtExceptionHandler;
public class NoCaughtThread {
public static void main(String[] args) {
// 設置未捕獲異常處理器,這裏是默認的,固然你能夠本身新建一個類,而後實現UncaughtExceptionHandler接口便可
Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.err.println("程序拋出了一個異常,異常類型爲 : " + e);
}
});
Thread thread = new Thread(new Task());
thread.start();
}
}
class Task implements Runnable {
@Override
public void run() {
throw new NullPointerException();
}
}
複製代碼
程序輸出:
程序拋出了一個異常,異常類型爲 : java.lang.NullPointerException
複製代碼
總結一下,歸根到底,我以爲之因此須要使用到UncaughtExceptionHandler
,不少狀況下都是由於咱們本身代碼寫的很差,不夠嚴謹,或者說咱們在寫代碼的時候沒有考慮周到。好比最多見的就是拋出空指針NullPointerException
,請看下面代碼:
Map<String, String> map = null;
System.err.println(map.get("name"));
複製代碼
上面的代碼一定拋出空指針異常,你可能會說,哇,誰這麼笨,這麼明顯聲明map=null
,好,爲了使你信服,我決定打個響指:
// 從數據庫查找一個用戶
User user = userDao.getUser(12);
System.err.println(user.getUserName("name"));
複製代碼
能夠看出,若是user
爲null
,則一定也是拋出空指針異常。不少不少非檢查異常咱們都須要儘可能避免,在編寫代碼的時候多考慮是否會出現空指針,是否會出現數組越界等等狀況。