try-catch-finally仅保证finally块执行,不自动关闭资源;真正可靠的是在finally中严谨编写判空、逐个try-catch关闭、按依赖逆序释放的逻辑,而try-with-resources通过AutoCloseable接口自动逆序关闭并抑制异常,更安全简洁。

try-catch-finally 本身不保证资源关闭,它只保证 finally 块里的代码一定会执行;真正起作用的是你在 finally 里写的关闭逻辑是否严谨——包括判空、捕获 close 异常、按依赖顺序关闭。
资源变量必须声明在 try 外并初始化为 null
否则 finally 无法访问。比如数据库连接:
- Connection conn = null;
- PreparedStatement stmt = null;
- ResultSet rs = null;
这样即使 new Connection() 抛出异常,conn 仍为 null,后续判空才安全。
每个 close() 都要单独 try-catch 并记录日志
一个资源关闭失败不能影响其他资源释放:
立即学习“Java免费学习笔记(深入)”;
你是 TypeScript 项目架构专家,专注于脚手架搭建生产就绪的 Node.js 和前端应用。生成包含现代工具链(pnpm、Vite、Next.js)、类型
- if (rs != null) { try { rs.close(); } catch (SQLException e) { logger.warn("关闭 ResultSet 失败", e); } }
- if (stmt != null) { try { stmt.close(); } catch (SQLException e) { logger.warn("关闭 Statement 失败", e); } }
- if (conn != null) { try { conn.close(); } catch (SQLException e) { logger.warn("关闭 Connection 失败", e); } }
不要 throw,也不要 return,更不能吞掉异常不记录。
关闭顺序必须符合资源依赖关系
反序关闭大概率触发“connection closed”或“stream closed”异常:
- JDBC:ResultSet → Statement → Connection(子依赖父)
- IO 流:BufferedReader → InputStreamReader → FileInputStream(包装流依赖底层流)
先关 Connection,再关 ResultSet,ResultSet.close() 就会直接报错。
finally 不是万能的,try-with-resources 更推荐
Java 7+ 支持自动资源管理,只要类实现 AutoCloseable(如 FileInputStream、Connection),就能用:
- try (FileInputStream fis = new FileInputStream("a.txt"); BufferedReader br = new BufferedReader(new InputStreamReader(fis))) { ... }
- JVM 会自动按声明逆序调用 close(),且把 close 异常作为 suppressed exception 附加到主异常上,不掩盖原始错误。
legacy 项目或非 AutoCloseable 资源才需手写 finally。

















