Java异常进阶

前言

先完成Java异常入门,再完成Java进阶。

一、自动关闭资源

JVM不回收硬件资源(如I/O资源),那是OS做的事,JVM会回收堆内存中对象所占用的资源。
平时I/O流出现IOException时,就会停止执行下面的代码,导致I/O流不能关闭。所以用Finally去回收。

public void testCheckedException() {
        FileReader reader = null;
        try {
            reader = new FileReader("d:\\a.txt");
            char ch = (char) reader.read();
        } catch (FileNotFoundException e) {
            //打印栈轨迹
            e.printStackTrace();
            //打印栈中信息
            StackTraceElement[] els = e.getStackTrace();
            for(StackTraceElement el : els){
                System.out.println("异常发生的类:"+ el.getClassName());
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

在JDK1.7之后,出现try_with_resources机制:
只要继承了AutoCloseable类的类,都可以在try语句块退出时,自动调用close方法关闭资源流。
在这里插入图片描述

public void testCheckedException2() {
        try(FileReader reader = new FileReader("d:\\a.txt"); FileOutputStream fos = new FileOutputStream("d:\\a.txt")) {
            char ch = (char) reader.read();
        } catch (FileNotFoundException e) {
            //打印栈轨迹
            e.printStackTrace();
            //打印栈中信息
            StackTraceElement[] els = e.getStackTrace();
            for(StackTraceElement el : els){
                System.out.println("异常发生的类:"+ el.getClassName());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

二、多异常捕获

当try语句中出现多种异常时,
1)可以用 | 来隔开。
2)如果一个catch语句块处理的异常类型超过一个(两类异常没有继承关系),那么被catch的参数变量隐式的变为final变量,在catch语句块中无法再将其赋值,即不能把当前的对象引用去指向其它对象。

public void testCheckedException2() {
        try(FileReader reader = new FileReader("d:\\a.txt"); FileOutputStream fos = new FileOutputStream("d:\\a.txt")) {
            char ch = (char) reader.read();
            int num = 2 / 0;
        } catch (IOException | ArithmeticException e) {
            //打印栈轨迹
            e.printStackTrace();
            //打印栈中信息
            StackTraceElement[] els = e.getStackTrace();
            for(StackTraceElement el : els){
                System.out.println("异常发生的类:"+ el.getClassName());
            }
        }
    }

三、异常处理嵌套

能用多catch语句替代异常处理嵌套吗?

public void embedException() {
        try {
            //程序A
            try {
                //程序B
            } catch (RuntimeException e) {
                //程序C
            } finally {
                //程序D
            }
            //程序E
        } catch (Exception e) {
            //程序F
        } finally {
            //程序G
        }
    }
public void embedException2() {
        try {
            //程序A
            //程序B
        } catch (RuntimeException e) {
            //程序C
        } catch (Exception e) {
            //程序F
        } finally {
            //程序D,以前的finally语句。
            //程序E
            //程序G
        }
    }

1)无异常:ABDEG
2)A 异常:AFG
注:A 异常,后面的BDE都将不会执行
3)B 异常:ABCDEG,当内层没有catch捕获到时,执行外层catch,又是另一种执行路径。
4)总结:当异常发生时,将停止后面的执行语句,处理完毕后,方可执行处理完毕后的语句。Finally语句必须执行。

四、catch + throws来包装异常

public void packException() throws Exception {
        try {
            int n = 2 / 0;
        } catch (ArithmeticException e) {
            throw new Exception("除数不能为0");
        }
    }

五、异常链追踪信息

捕获异常后再抛出异常,并希望把原始造成异常的异常信息保存并传递下去,被称作异常链。

public void packException2() throws Exception {
        try {
            int n = 2 / 0;
        } catch (ArithmeticException e) {
            throw new Exception("除数不能为0",e);
        }
    }
/**
     * Constructs a new exception with the specified detail message and
     * cause.  <p>Note that the detail message associated with
     * {@code cause} is <i>not</i> automatically incorporated in
     * this exception's detail message.
     *
     * @param  message the detail message (which is saved for later retrieval
     *         by the {@link #getMessage()} method).
     * @param  cause the cause (which is saved for later retrieval by the
     *         {@link #getCause()} method).  (A {@code null} value is
     *         permitted, and indicates that the cause is nonexistent or
     *         unknown.)
     * @since  1.4
     */
    public Exception(String message, Throwable cause) {
        super(message, cause);
    }

六、友好的throws语句

public void friendlyThrows() throws IOException {
        try (FileReader reader = new FileReader("d:\\a.txt")){
            //操作文件
        }catch (Exception e){
            //操作异常
            throw e;
        }
    }

当我们catch到Exception时,然后throw出去,Java编译器会细致检查实际异常,然后throws出真实异常IOException.

总结

1)自动关闭资源
2)多异常捕获
3)异常处理嵌套
4)catch + throws来包装异常
5)异常链追踪信息
6)友好的throws语句

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值