Try-catch() 对于流的新用法(try-with-resources,try后加括号 ), 以及异常新方法addSuppressed(针对异常屏蔽)

Java7 开始 ,针对stream流的close()操作有了新的写法。
之前我们都要在finally中执行close()方法,如果用到了多个流,要写不少的多余代码,finally中全是close(),而且我们的写法还不一定安全(大佬可能会避免)。如下代码:
首先贴上我的两个自定义流:

class MyFileOutputStream extends FileOutputStream {

    MyFileOutputStream(String name) throws FileNotFoundException {
        super(name);
    }

    @Override
    public void close() throws IOException {
        System.out.println(">>>>MyFileOutputStream close");
        throw new IOException("Exception in MyFileOutputStream close()");
    }

    public void read() {
        System.out.println(">>>>MyFileOutputStream read");
    }

}

class MyZipOutputStream extends ZipOutputStream {

    public MyZipOutputStream(OutputStream out) {
        super(out);
    }
    
    @Override
    public void close() {
        System.out.println(">>>>MyZipOutputStream close");
    }

    public void read() throws IOException {
        System.out.println(">>>>MyZipOutputStream read");
        throw new IOException("Exception in MyZipOutputStream read()");
    }
}

关闭流的测试方法:

public static void test() throws Exception {
        MyFileOutputStream file = null;
        MyZipOutputStream out = null;
        try {
            file = new MyFileOutputStream("E:\\ppp.txt");
            out = new MyZipOutputStream(file);
            out.read();
        } catch (Exception e) {
            System.out.println("MyZipOutputStream read error");
            throw new BaseException(e);
        } finally {
            if (null != file) {
                file.close();
            }
            if (null != out) {
                out.close();
            }
        }
    }

main方法:

		try {
            test();
        } catch (Exception e) {
            e.printStackTrace();
        }

执行结果:(注意:file.close();是发生了异常的)
在这里插入图片描述
可以看到,zip流并没有被关闭,因为在finally中file.close()发生了异常,导致后边的out.close() 没有执行。所以我们大部分的写法是有隐患的,并不完全正确。

下面采用try-with-resources的新写法:

try (MyFileOutputStream file = new MyFileOutputStream("E:\\ppp.txt");
             MyZipOutputStream o = new MyZipOutputStream(file)
        ) {
            o.read();
        } catch (Exception e) {
            System.out.println("read  catch");
            e.printStackTrace();
        }

新写法的结果:
在这里插入图片描述
可以看到,即使发生异常,在cache前对这种方式对两个流都进行了关闭,而且写法简单,代码简洁又安全。看下编译后的class文件:

try {
            MyFileOutputStream file = new MyFileOutputStream("E:\\ppp.txt");
            Throwable var3 = null;

            try {
                MyZipOutputStream o = new MyZipOutputStream(file);
                Throwable var5 = null;

                try {
                    o.read();
                } catch (Throwable var30) {
                    var5 = var30;
                    throw var30;
                } finally {
                    if (o != null) {
                        if (var5 != null) {
                            try {
                                o.close();
                            } catch (Throwable var29) {
                                var5.addSuppressed(var29);
                            }
                        } else {
                            o.close();
                        }
                    }

                }
            } catch (Throwable var32) {
                var3 = var32;
                throw var32;
            } finally {
                if (file != null) {
                    if (var3 != null) {
                        try {
                            file.close();
                        } catch (Throwable var28) {
                            var3.addSuppressed(var28);
                        }
                    } else {
                        file.close();
                    }
                }

            }
        } catch (Exception var34) {
            System.out.println("read  catch");
            var34.printStackTrace();
        }

Java替我们生成了安全的写法(应该也是大佬的写法),不用我们去费功夫了。该语法会自动对实现了AutoCloseable(Java7)接口的类进行关闭,而原来的Closeable继承了该接口。

**这里还有一个点,**第一个旧的打印结果中,明明read方法也发生了异常,但是最后抛出的异常只有close,这就是异常屏蔽。但是新的结果打印了两个异常,请注意这个词:Suppressed:,这个就是Java7 新增的修复异常屏蔽的方法,就是Throwable.addSuppressed() 方法,看编译后的class文件,就用到了这个写法,就是把捕获的异常加到异常列表中,具体可以看源码:

private List<Throwable> suppressedExceptions = SUPPRESSED_SENTINEL;

public final synchronized void addSuppressed(Throwable exception) {
        if (exception == this)
            throw new IllegalArgumentException(SELF_SUPPRESSION_MESSAGE, exception);

        if (exception == null)
            throw new NullPointerException(NULL_CAUSE_MESSAGE);

        if (suppressedExceptions == null) // Suppressed exceptions not recorded
            return;

        if (suppressedExceptions == SUPPRESSED_SENTINEL)
            suppressedExceptions = new ArrayList<>(1);

        suppressedExceptions.add(exception);
    }
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值