effective java 第9条:try-with-resources优先于try-finally

文章讨论了在Java中管理需要关闭的资源,如InputStream和OutputStream,如何从使用try-finally语句避免资源泄露演进到使用try-with-resources语句进行更优雅的资源管理。try-with-resources确保了资源的自动关闭,并在多异常情况下更好地保留异常信息,简化了代码并提高了可读性。
摘要由CSDN通过智能技术生成

java类库中包括许多必须通过调用close方法来手工关闭的资源。例如InputStream、OutputStream...,客户端经常会忘记关闭资源,造成严重的性能后果。虽然这其中的许多资源都是用终结方法(慎用终结方法)作为安全网,但是效果并不理想。

1、try-finally 

根据经验,try-finally 语句是确保关闭资源的最佳方法,就算发生异常或者返回也一样

static String firstLineOfFile(String path) throws IOException {
    BufferedReader br = new BufferedReader(new FileReader(path));
    try {
        return br.readLine();
    } finally {
        br.close();
    }
}

 但是如果再添加第二个资源,就会一团糟

static void copy(String src, String dst) throws IOException {
    InputStream in = new FileInputStream(src);
    try {
        OutputStream out = new FileOutputStream(dst);
        try {
            byte[] buf = new byte[FileCopyUtils.BUFFER_SIZE];
            int n;
            while ((n = in.read(buf)) >= 0) {
                out.write(buf,0,n);
            }
        } finally {
            out.close();
        }
    } finally {
        in.close();
    }
}

 即便用try-finally语句正确的关闭了资源,也存在着些许的不足。因为try块和finally块都会抛出异常。例如,在firstLineOfFile方法中,如果底层的物理设备异常,那么调用readLine就会抛出异常,基于同样的原因,调用close也会发生异常。在这种情况下,第二个异常完全抹除了第一个异常,在异常堆栈轨迹中,完全没有第一个异常的记录,这在现实的系统中,会导致调试变得非常复杂。虽然可以通过编写代码来禁止第二个异常,保留第一个异常,但是事实上实现起来太繁琐了。

当是使用try-with-resources语句时,这些问题就全部解决了。

2、try-with-resources

要使用这个构造的资源,必须先实现AutoCloseable接口,其中包含单个返回void和close方法。

以下使用try-with-resources改造第一个示例

static String firstLineOfFile(String path) throws IOException {
    try (BufferedReader br = new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

一下改造第二个示例

static void copy(String src,String dst) throws IOException{
    try(InputStream in = new FileInputStream(src);
        OutputStream out = new FileOutputStream(dst)) {
        byte[] buf = new byte[FileCopyUtils.BUFFER_SIZE];
        int n;
        while ((n = in.read(buf))>0) {
            out.write(buf,0,n);
        }
    }
}

 

使用 try-with-resources不仅是代码变得更简洁易懂,也更容易诊断。以firstLineOfFile方法为例,如果调用readLine和(不可见的)close方法都抛出异常,后一个异常就会被禁止,已保留第一个异常。

为了保留你想看到的异常,即便多个异常被禁止,这些异常并不是简单的被抛弃了,而是会打印在堆栈轨迹中,并注明它们是被禁止的异常。通过调用getSuppressed方法还可以访问到它们。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值