应优先使用try-with-resources管理AutoCloseable资源,按后声明先关闭顺序自动释放;非AutoCloseable资源(如锁、线程池)须在finally中显式释放,并注意判空、异常隔离和关闭顺序。

多资源释放不是简单堆几个close()就行,关键在顺序、异常隔离和资源状态安全。Java 7+ 应该用 try-with-resources 为主力,finally 仅作补充或兜底。
优先用 try-with-resources 管理 AutoCloseable 资源
所有标准 I/O 流(FileInputStream、BufferedReader)、JDBC 对象(Connection、Statement、ResultSet)都实现了 AutoCloseable,天然适配:
- 资源在
try括号内声明,生命周期由 JVM 自动绑定 - 关闭顺序严格按“后声明先关闭”,避免依赖关系出错(比如先关
BufferedReader,再关底层FileInputStream) - 即使某个
close()抛异常,它会被压制(suppressed),主异常仍可捕获和处理 - 编译器强制检查是否为可关闭类型,不会漏写或写错
多个资源嵌套时的写法示例
不用手动判空、不用层层 try-catch,清晰且安全:
try (FileInputStream in = new FileInputStream("in.txt");
FileOutputStream out = new FileOutputStream("out.txt");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(out))) {
String line;
while ((line = reader.readLine()) != null) {
writer.write(line);
writer.newLine();
}
} catch (IOException e) {
// 主异常在此统一处理
}
上面四类资源会在退出 try 块时自动按 writer → reader → out → in 逆序关闭。
立即学习“Java免费学习笔记(深入)”;
finally 适合补位非 AutoCloseable 资源
当遇到不实现 AutoCloseable 的资源时,finally 才是真正不可替代的:
-
显式锁:如
ReentrantLock.lock()后,必须在finally中调用unlock(),否则可能永久阻塞其他线程 -
线程池关闭:
ExecutorService不是AutoCloseable,需在finally中调用shutdown()+awaitTermination()或shutdownNow() -
本地内存或句柄:通过
Unsafe分配的内存、JNI 返回的 native 句柄,必须在finally显式释放,必要时搭配Cleaner(Java 9+)做最终保障
手写 finally 释放时的关键细节
若因兼容旧版本或特殊资源不得不手动写 finally,务必注意:
- 每个资源关闭前必须判空:
if (resource != null),防止NullPointerException - 每个
close()单独包裹try-catch,避免一个失败中断后续关闭 - 不要在
finally中return或throw,否则会覆盖原始异常或返回值 - 多个资源释放顺序要合理,例如数据库连接应在
ResultSet和Statement之后关闭(尽管它们本身支持try-with-resources)


















