在 try-with-resources 中,资源声明顺序即初始化顺序,关闭则严格按后进先出(lifo)逆序执行:最右者最先关闭,最左者最后关闭,确保依赖资源安全释放。

在 Java 的 try-with-resources 语句中,多个资源的声明顺序直接决定了它们的**初始化顺序**和**关闭顺序**:资源按从左到右声明,初始化也从左到右;而关闭则严格遵循**后进先出(LIFO)**,即最右边声明的资源最先关闭,最左边的最后关闭。
资源声明顺序 = 初始化顺序
Java 按照你在 try 括号内书写的顺序依次调用每个资源的构造方法或工厂方法。例如:
try (FileInputStream fis = new FileInputStream("a.txt");
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
PrintWriter pw = new PrintWriter("out.txt")) {
// ...
}
这里会先创建 fis,再用它构造 br,最后创建 pw。如果某一步抛出异常(如文件不存在),后续资源不会被尝试初始化。
关闭顺序严格逆序(LIFO)
无论资源之间是否有依赖关系,JVM 总是按声明的**反向顺序**调用 close():
- pw.close() 先执行
- br.close() 次之
- fis.close() 最后执行
这种设计确保了“被依赖者”(如 br 依赖 fis)总是在依赖者(fis)之前关闭,避免在关闭过程中因底层资源已释放而引发异常或静默失败。
依赖资源必须显式按依赖链顺序声明
若资源存在逻辑依赖(比如包装流),你必须把被包装者写在前面,包装者写在后面,否则可能在初始化时就失败:
- ✅ 正确(fis 在前,br 依赖 fis):
new FileInputStream(...) ; new BufferedReader(...) - ❌ 错误(br 在前,但无法构造,因为 fis 还没声明):
new BufferedReader(...) ; new FileInputStream(...)→ 编译不通过
注意:你不能在声明中跨资源引用未声明的变量(如不能在第一个分号前用第二个资源的变量),所以依赖关系天然由书写顺序约束。
异常抑制与关闭失败的处理
关闭阶段某个资源抛出异常时:
- 如果 try 块本身已抛异常,该关闭异常会被抑制(suppressed),可通过
Throwable.getSuppressed()获取 - 关闭仍会继续执行其余资源的
close(),不会中断整个关闭流程 - 因此,即使
pw.close()失败,br和fis依然会被尝试关闭
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











