首页 > Java > java教程 > 正文

java如何使用try-with-resources简化资源关闭 java资源关闭简化的实用教程操作​

雪夜
发布: 2025-08-03 18:31:01
原创
130人浏览过

try-with-resources 解决了资源泄露、代码冗余和异常处理不优雅三大痛点,1. 它通过自动关闭实现 autocloseable 接口的资源,确保无论 try 块正常或异常结束,资源都会被可靠释放;2. 它将资源声明与使用集中在 try 括号内,消除了繁琐的 finally 块,使代码更简洁清晰;3. 当 try 块异常与 close() 异常同时发生时,close() 异常会被作为被抑制异常添加到主异常中,保留完整异常信息;4. 要使用该特性,资源类必须实现 autocloseable 接口并在 close() 方法中定义释放逻辑;5. 最佳实践中应直接在 try 括号内声明并初始化资源,仍需 catch 处理业务异常,并注意 close() 异常可能被抑制但可通过 getsuppressed() 获取,该特性仅适用于需显式关闭的资源,是现代 java 开发推荐的标准做法。

java如何使用try-with-resources简化资源关闭 java资源关闭简化的实用教程操作​

try-with-resources
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
是 Java 7 引入的一个语法糖,它让资源管理变得异常简洁和安全,核心就是自动关闭那些实现了
AutoCloseable
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
接口的资源,彻底告别了
finally
登录后复制
登录后复制
登录后复制
登录后复制
块里手动关闭资源的繁琐和潜在的资源泄露问题。我个人觉得这简直是 Java 给开发者的一大福音,写起代码来心里踏实多了。

解决方案

使用

try-with-resources
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
的语法非常直观:在
try
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
关键字后面的括号里声明或初始化需要关闭的资源。这些资源必须是实现了
java.lang.AutoCloseable
登录后复制
登录后复制
接口的类型。当
try
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
块执行完毕,无论正常结束还是发生异常,括号内声明的所有资源都会被自动、可靠地关闭。

比如,以前我们读文件,代码可能是这样的:

立即学习Java免费学习笔记(深入)”;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class OldWay {
    public static void main(String[] args) {
        BufferedReader reader = null;
        try {
            reader = new BufferedReader(new FileReader("example.txt"));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            System.err.println("读取文件时发生错误: " + e.getMessage());
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    System.err.println("关闭资源时发生错误: " + e.getMessage());
                }
            }
        }
    }
}
登录后复制

现在,有了

try-with-resources
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
,代码变得干净许多:

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class NewWay {
    public static void main(String[] args) {
        try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            System.err.println("读取文件时发生错误: " + e.getMessage());
        }
    }
}
登录后复制

可以看到,那个冗长的

finally
登录后复制
登录后复制
登录后复制
登录后复制
块完全消失了,代码意图也更清晰。如果有多个资源需要管理,可以在括号内用分号隔开,它们会按照声明的逆序自动关闭。

try-with-resources
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
到底解决了哪些痛点?

这玩意儿的出现,真的解决了我们开发者好几个心头大患。

首先是资源泄露的问题。以前写代码,最怕的就是资源忘了关,或者在异常路径下没关上,那真是噩梦。比如数据库连接、文件流、网络Socket,这些东西一旦没关,轻则拖慢系统,重则直接把服务器搞崩。手动管理

finally
登录后复制
登录后复制
登录后复制
登录后复制
块里
close()
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
方法,总会担心是不是哪个分支漏了,或者
close()
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
自己也抛异常了怎么办。
try-with-resources
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
就像一个贴心的管家,它保证了资源在
try
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
块结束时,无论如何都会被关闭,哪怕中间抛了异常。

其次是代码的冗余。那些

try-finally
登录后复制
登录后复制
结构,尤其是嵌套的
try-finally
登录后复制
登录后复制
,看着就头疼,写起来更是一堆样板代码。它把业务逻辑和资源管理混在一起,降低了代码的可读性。现在,资源声明直接放在
try
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
括号里,一眼就能看出哪些资源被管理了,核心的业务逻辑也更突出了,代码干净了不少。对我来说,这大大提升了编码效率和心情。

再来就是异常处理的优雅。如果

try
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
块里抛了异常,同时资源关闭(
close()
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
方法)也抛了异常,
try-with-resources
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
会把
close()
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
方法抛出的异常作为“被抑制的异常”(suppressed exception)添加到原始异常中。这意味着你不会丢失任何异常信息,这比手动处理要智能和健壮得多。你依然可以通过
Throwable.getSuppressed()
登录后复制
方法来获取这些被抑制的异常。

并非所有资源都能用,
AutoCloseable
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
接口是关键

要让一个资源能被

try-with-resources
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
管理,它必须实现
java.lang.AutoCloseable
登录后复制
登录后复制
接口。这个接口非常简单,只有一个方法:
void close() throws Exception;
登录后复制

Java 标准库中很多类都实现了这个接口,比如各种

InputStream
登录后复制
OutputStream
登录后复制
Reader
登录后复制
Writer
登录后复制
的子类,还有
java.sql
登录后复制
包下的
Connection
登录后复制
Statement
登录后复制
ResultSet
登录后复制
等。这些都是我们日常开发中经常需要关闭的资源。

那如果我自己写了个类,它管理着一些需要在使用后释放的资源(比如一个自定义的网络连接池,或者一个需要关闭的本地资源句柄),怎么让它也能享受

try-with-resources
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
的便利呢?很简单,让你的类实现
AutoCloseable
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
接口,并在
close()
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
方法里实现资源的释放逻辑就行了。

class MyCustomResource implements AutoCloseable {
    private String name;

    public MyCustomResource(String name) {
        this.name = name;
        System.out.println(name + " 资源被打开了。");
    }

    public void doSomething() {
        System.out.println(name + " 正在执行一些操作...");
        // 模拟可能抛出异常的操作
        // if (Math.random() > 0.5) {
        //     throw new RuntimeException(name + " 操作失败了!");
        // }
    }

    @Override
    public void close() throws Exception {
        System.out.println(name + " 资源被关闭了。");
        // 模拟关闭时可能抛出异常
        // if (Math.random() > 0.8) {
        //     throw new IOException(name + " 关闭时发生错误!");
        // }
    }
}

public class CustomResourceDemo {
    public static void main(String[] args) {
        try (MyCustomResource res1 = new MyCustomResource("资源A");
             MyCustomResource res2 = new MyCustomResource("资源B")) {
            res1.doSomething();
            res2.doSomething();
            // 如果这里抛出异常,res1和res2依然会被关闭
        } catch (Exception e) {
            System.err.println("捕获到异常: " + e.getMessage());
            for (Throwable suppressed : e.getSuppressed()) {
                System.err.println("被抑制的异常: " + suppressed.getMessage());
            }
        }
    }
}
登录后复制

运行上面这段代码,你会看到无论

doSomething()
登录后复制
是否抛出异常,
MyCustomResource
登录后复制
close()
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
方法都会被调用。这就是
AutoCloseable
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
的魔力。

实际开发中,
try-with-resources
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
的误区与最佳实践

尽管

try-with-resources
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
非常好用,但实际开发中还是有一些需要注意的地方,或者说,我见过一些开发者在使用时会犯的小错误。

一个常见的误区是,有人觉得它能解决所有资源管理问题。不,它只针对那些实现了

AutoCloseable
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
的资源。如果你有一个资源没有实现这个接口,或者它不需要显式关闭(比如一个简单的 POJO 对象),那
try-with-resources
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
就帮不上忙了。它不是万能药,但对于可关闭资源,它确实是目前最好的实践。

关于最佳实践:

首先,资源的声明应该直接在

try
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
语句的括号里完成。我见过一些代码,把资源在外面声明了,然后
try
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
里面再赋值,这样
try-with-resources
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
就失效了,因为它只管理在括号里声明并初始化的资源。例如:

// 错误示例:资源不会被自动关闭
BufferedReader reader;
try (reader = new BufferedReader(new FileReader("example.txt"))) {
    // ...
} catch (IOException e) {
    // ...
}
// reader在这里可能未被关闭
登录后复制

正确的做法是:

// 正确示例:资源会被自动关闭
try (BufferedReader reader = new BufferedReader(new FileReader("example.txt"))) {
    // ...
} catch (IOException e) {
    // ...
}
登录后复制

其次,虽然

try-with-resources
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
帮你处理了资源的关闭,但你仍然需要一个
catch
登录后复制
块来处理业务逻辑可能抛出的异常。它只负责“清理”,不负责“业务逻辑错误”的处理。所以,不要因为有了它就忽略了异常捕获。

再者,如果

close()
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
方法本身抛出了异常,这个异常会被抑制。虽然这通常不是问题,但了解这个机制很重要。在某些极端情况下,如果你需要对
close()
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
抛出的异常做特殊处理,可以通过
getSuppressed()
登录后复制
方法来获取。不过,大部分时候,我们并不需要特别关心这些被抑制的关闭异常,因为它们通常意味着资源已经尝试关闭,只是关闭过程中出了点小岔子,不影响主业务逻辑的异常处理。

最后,一旦用上了

try-with-resources
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
,就很难回到过去那种写
finally
登录后复制
登录后复制
登录后复制
登录后复制
的日子了。它不仅让代码更简洁,也大大降低了资源泄露的风险。所以,养成习惯,凡是遇到需要关闭的资源,优先考虑
try-with-resources
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
登录后复制
。这是一种更现代、更健壮的 Java 编程风格。

以上就是java如何使用try-with-resources简化资源关闭 java资源关闭简化的实用教程操作​的详细内容,更多请关注php中文网其它相关文章!

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 //m.sbmmt.com/ All Rights Reserved | php.cn | 湘ICP备2023035733号