駱駝官方旗艦店:工裝馬丁靴 189 元探底(京東 418 元)
異常
+-------------------------------+
| Throwable |
| / \ |
| / \ |
| Error Exception |
| / \ |
| / \ |
| Runtime Other |
+-------------------------------+
-
Runtime Exception是unchecked未受檢異常,Other是checked檢查異常。通常在程式中處理的都是受檢異常。
-
Exception類是應該被程式捕獲處理的;而Error同樣也可以被捕獲,但通常是JVM出現異常,這些嚴重的問題程式不應該捕獲。所以不能直接捕獲Throwable,而應該具體到Exception類。
受檢異常和非受檢異常
-
受檢異常 Other Exception
Java 在編譯時就驗證受檢異常。 因此我們需要丟擲或者捕獲處理這些異常。
常見的受檢異常有IOException 、 SQLException 和 ParseException
我們可以通過繼承 Exception 類來實現自定義的受檢異常
-
非受檢異常 Runtime Exception
Java 不會在編譯時驗證非經受檢的異常。這類異常通常反映了程式邏輯的一些錯誤。
不受檢我們也就不用捕獲和丟擲,但是執行時如果有錯將會丟擲異常。
常見的是是 NullPointerException 、 ArrayIndexOutOfBoundsException
我們可以通過繼承 RuntimeException 來實現自定義的非受檢異常
-
什麼時候使用受檢異常,什麼時候使用非受檢異常?
“如果可以合理地期望客戶端從異常中恢復,請將其設為已檢查的異常。 如果客戶端無法從異常中恢復,請將其設為非經檢查的異常。” -Oracle
try-with-source
java7引入,我們可以在try後括號內宣告和初始化資源,執行完try塊資源將自動關閉。
- 資源必須實現了AutoCloseable或Closeable介面
- 要自動關閉,必須在括號內宣告和初始化資源
- 可以宣告多個資源,用分號分隔
- 先宣告的資源先初始化,但最後關閉
全域性異常捕獲
自從1.5開始,Java 的 Thread 類中提供了 UncaughtExceptionHandler 介面。
@FunctionalInterface
public interface UncaughtExceptionHandler {
void uncaughtException(Thread t, Throwable e);
}
// null unless explicitly set
private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(
new RuntimePermission("setDefaultUncaughtExceptionHandler")
);
}
defaultUncaughtExceptionHandler = eh;
}
要使用java提供的全域性異常處理,我們需要實現一個 UncaughtExceptionHandler 的 Handler 類,並實現 uncaughtException 方法,該執行緒非被捕獲的異常都將在這裡處理,通常我們進行日誌記錄。然後執行緒有一個 defaultUncaughtExceptionHandler 屬性,我們要將其設定為我們實現的 Handler 類。看看具體怎麼做:
public class Test {
public static void main(String[] args) {
Handler globalExceptionHandler = new Handler();
Thread.setDefaultUncaughtExceptionHandler(globalExceptionHandler);
System.out.println(10/0);
}
}
class Handler implements Thread.UncaughtExceptionHandler {
private static Logger LOGGER = LoggerFactory.getLogger(Handler.class);
public void uncaughtException(Thread t, Throwable e) {
LOGGER.info("Unhandled exception caught!");
}
}
Runtime異常都可以被捕獲,受檢異常也可以丟擲給它處理。
不過,這打破了就近捕獲和處理異常的規則,在很多框架中都使用了全域性異常。