Java异常

Java异常

Java异常体系图

在这里插入图片描述

Exception的子类有很多,主要可概括为运行时异常和非运行时异常

Java异常体系结构

Throwable类时是所有异常的错误的超类,两个直接子类为Error和Exception,分别表示错误和异常,其中异常类Exception又分为运行时异常和非运行时异常,这两种异常有很大区别。

  1. Error和Exception
    Error是程序无法处理的错误,他是有JVM产生和抛出的,比如OutOfMemoryError,ThreadDeath等。这些异常发生时,Java虚拟机JVM一般会选择线程终止。Exception是程序本身可以处理的异常,这种异常分为两大类,运行时异常和非运行时异常。程序中应当尽可能去处理这些异常
  2. 运行时异常和非运行时异常
    运行时异常都是RuntimeException类及其子类异常,如NullPointException、IndexOutOfBoundsException等,这些异常可以再运行的过程中不被检查,程序可以选择捕获这些异常,也可以选择不捕获这些异常。这些异常一般是由程序逻辑错误引起的,程序应该从逻辑角度尽可能避免这类异常的发生。非运行时异常时RuntimeException以外的异常,类型上都属于Exception类及其子类。从程序语法角度讲必须进行处理的异常,如果不处理,程序就不能通过,如IOException,SQLException等等。

异常的捕获与处理

常见的异常捕获为以下方式

try{

}catch(Exception e1){

}catch(Exception e2){

}finally{

}

注意事项:

  1. try、catch、finally三个语句块均不能单独使用,三者可以组成try…catch…finally,try…catch,try…finally三种结构,catch语句可以有一个或者多个,finally语句只能有一个
  2. try、catch、finally三个代码块中变量的作用域为代码块内部,分别独立而不能相互访问。如果要在三个块中都可以访问,则需要将变量定义到这些块的外面。
  3. 多个catch块时候,最多只会匹配其中一个异常类且只会执行该catch块代码,而不会再执行其它的catch块,且匹配catch语句的顺序为从上到下,也可能所有的catch都没执行。

try…catch…finally只能捕获本线程抛出的异常,其他线程抛出的异常则无法捕获,下面为代码演示

public class UseOwnUncaughtException {
    public static void main(String[] args) {
        //Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtException("lym"));
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                throw new RuntimeException();
            }
        };
        try{
            new Thread(runnable).start();
            new Thread(runnable).start();
            new Thread(runnable).start();
        }catch (RuntimeException e){
            e.printStackTrace();
        }
    }
}

那么如何全局处理异常?为什么要全局处理,不处理行不行?

全局异常有两种处理方法:

  1. 在每个子线程中都捕获异常
  2. 在主线程中使用UncaughtExceptionHandler

使用该Handler的原因:主线程中可以轻松发现异常,子线程却不行,子线程抛出未捕获异常主线程不受影响,正常执行。

UncaughtExceptionHandler的调用策略

public class ThreadGroup implements Thread.UncaughtExceptionHandler{
    public void uncaughtException(Thread t,Throwable e){
        //默认情况下parent是null
        if(parent!=null){
            parent.uncaughtException(t,e);
        }else{
            //调用Thread.setDefaultUncaughtExceptionHandler()
            Thread.UncaughtExceptionHandler ueh = Thread.getDefaultUncaughtExceptionHandler();
            if(ueh != null){
                ueh.uncaughtException(t,e);
            }else if(!(e instanceof ThreadDeath)){
                System.err.print("Exception in thread" + t,getName);
                e.printStackTrace(System.err);
            }
        }
    }
}

UncaughtExceptionHandler的使用方法

由上述代码可知,如果父类为null的情况下,会调用Thread.setDefaultUncaughtexceptionHandler接口的uncaughtException方法,所以我们需要实现Thread.setDefaultUncaughtexceptionHandler接口并重写该方法。下面为具体的代码演示。

public class MyUncaughtException implements Thread.UncaughtExceptionHandler {
    private String name;
    public MyUncaughtException(String name){
        this.name = name;
    }
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        Logger logger = Logger.getAnonymousLogger();
        logger.log(Level.WARNING,"线程异常终止啦" + t.getName(),e);
        System.out.println(name+"捕获的异常");
    }
}
public class UseOwnUncaughtException {
    public static void main(String[] args) {
        //Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtException("lym"));
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                throw new RuntimeException();
            }
        };
        try{
            new Thread(runnable).start();
            new Thread(runnable).start();
            new Thread(runnable).start();
        }catch (RuntimeException e){
            e.printStackTrace();
        }
    }
}

try-catch-finally代码块的执行顺序

  • try没有捕获异常时,try代码块中的语句依次被执行,跳过catch。如果存在finally则执行finally代码块,否则执行后续代码。
  • try捕获到异常时,如果没有与之匹配的catch子句,则该异常交给JVM处理。如果存在finally,则其中的代码仍然被执行,但是finally之后的代码不会被执行。
  • try捕获到异常时,如果存在与之匹配的catch,则跳到该catch代码执行处理。如果存在finally则执行finally代码块,执行完finally代码块之后继续执行后续代码,否则直接执行后续代码,另外注意,try代码块出现异常之后的代码不会被执行。
    try代码块:用于捕获异常,其后可以接零个或者多个catch快。如果没有catch快,后面必需跟finally快,来完成资源释放等操作,另外不建议在finally中使用return。不用尝试通过catch来控制代码流程。
    catch代码块:用于捕获异常,并在其中处理异常。finally代码块:用于捕获异常,finally代码总会执行。如果try代码块或者catch代码块中有return语句时,finally代码块将在方法返回前被执行。注意一下几种情况。finally不会被执行。
  1. 在前边的代码中使用System.exit()退出应用。
  2. 程序所在的线程死亡或者cpu关闭
  3. 如果在finally代码块中的操作有产生异常,则该finally代码块不能完全执行结束,同时异常会覆盖前边抛出的异常。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值