Java语言提供了异常处理机制,在日常编码中使用Exception的频率很高,而Error的使用频率相对较低一些,本篇博客主要针对这两种类型的异常进行分析。
Exception 和 Error 都继承自Throwable,在 Java 中只有Throwable类型的实例才可以被抛出或者捕获,它是异常处理机制的基本组成类型。异常Exception和错误Error 的本质区别在于:异常能被程序本身处理,而错误无法处理。
下图是三者之间的关系:
Error
相比于Exception来说更严重,是程序不能处理的系统错误类,如内存溢出、虚拟机错误、线程死锁等。这类错误一般与硬件有关,与程序本身无关,通常由系统进行处理,程序本身无法捕获和处理。
Exception
表示程序可以处理的异常,可捕获和恢复。日常编程中应该尽可能处理异常,使程序恢复运行,而不应该随意终止异常。
Exception 可以分为可检查异常(checked)和非检查型异常(unchecked)。
可检查异常(checked)
也称非运行时异常,java编译器强制程序员必须进行捕获处理,比如常见的IOExeption和SQLException。对于非运行时异常如果不进行捕获或者抛出声明处理,编译都不会通过。
非检查型异常(unchecked)
也称运行时异常(RuntimeException),比如常见的NullPointerException、IndexOutOfBoundsException。由程序员自行决定是否进行异常捕获处理或者抛出声明处理。
Exception处理的2个基本原则
1.尽量捕获特定异常而不是通用异常。
如果捕获通用异常,会隐藏异常的详细信息,不利于其他程序员阅读自己的代码。所以针对已知类型的
2.不要生吞(swallow)异常。
生吞异常是指对异常进行捕获后,没有进行有效的处理以及输出,这样相当于忽略了当前异常,不利于发生异常后的排查和恢复。
多线程中的异常捕获
多线程不能按照顺序执行过程中捕获异常的方式来处理异常,直接在主线程中是捕获不到子线程中的异常的,所以需要进行特殊处理:
自定义异常处理器,并设定到对应的线程工厂中。
(1).定义异常处理器
class MyExceptionHandler implements Thread.UncaughtExceptionHandler{
//以下方法会在线程临近死亡时被调用
@Override
public void uncaughtException(Thread t, Throwable e) {
Logger.info("捕获异常:"+e);
}
}
(2).定义使用该异常处理器的线程工厂
class HanlderThreadFactory implements ThreadFactory{
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
Logger.info("创建新线程:"+t);
//设定线程工厂的异常处理器
t.setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
Logger.info("异常处理器="+t.getUncaughtExceptionHandler());
return t;
}
}
(3).定义一个会抛出异常的线程
class MyExceptionThread implements Runnable{
@Override
public void run() {
Thread t = Thread.currentThread();
Logger.info("异常处理器: "+t.getUncaughtExceptionHandler());
throw new RuntimeException();
}
}
(4).使用线程工厂创建线程池,并调用其execute方法
public class ThreadExceptionTest{
public static void main(String[] args){
ExecutorService exec = Executors.newCachedThreadPool(new HanlderThreadFactory());
//执行自定义的线程
exec.execute(new MyExceptionThread());
}
}
线程异常捕获参考了以下博客,表示感谢~:
https://blog.csdn.net/sanyaoxu_2/article/details/79162953