今天在看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
,则一定也是抛出空指针异常。不少不少非检查异常咱们都须要尽可能避免,在编写代码的时候多考虑是否会出现空指针,是否会出现数组越界等等状况。