196. Java 异常 - Try-with-Resources:自动关资源的神器!

47 阅读2分钟

196. Java 异常 - Try-with-Resources:自动关资源的神器!


🧠 什么是 try-with-resources?

Java 中,有些对象用完之后必须关闭,比如:文件、数据库连接、网络流等。这些对象被称为 资源(resources

Java 7 起,提供了一个新语法叫:

🔧 try-with-resources:自动关闭资源的 try

相比以前写 try-finally 手动关闭资源的方式,它更简洁、更安全。


✅ 用法一览

try (ResourceType name = new ResourceType()) {
    // 使用资源
} catch (...) {
    // 异常处理
} finally {
    // 可选的收尾
}
  • ✅ 所有资源在 } 之后自动关闭
  • ✅ 顺序是:先声明的后关闭
  • ✅ 所有资源类型必须实现 AutoCloseable 接口(比如 Closeable

💡 例子:读取文件的第一行

🔎 Java 7+ 推荐写法:

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

👍 没有 finally,代码清爽,BufferedReader 会被自动关闭!


Java 7前的传统写法:

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

⚠️ 如果 readLine()close() 都抛异常,只有 finally 中的异常会被抛出,前面的异常会被“吃掉”!


🔁 多个资源怎么办?

你可以在 try 中声明多个资源,用 ; 分隔:

try (
    ZipFile zf = new ZipFile(zipFileName);
    BufferedWriter writer = Files.newBufferedWriter(outputFilePath, charset)
) {
    for (Enumeration<? extends ZipEntry> entries = zf.entries(); entries.hasMoreElements();) {
        String entryName = entries.nextElement().getName() + System.lineSeparator();
        writer.write(entryName);
    }
}

🧹 退出 try 块后,writerzf 都会被自动关闭!而且是先关闭 writer,后关闭 zf(后创建的先关闭)。


☕ 示例:数据库查询也能用!

public static void viewTable(Connection con) throws SQLException {
    String query = "SELECT COF_NAME, SUP_ID, PRICE, SALES, TOTAL FROM COFFEES";

    try (Statement stmt = con.createStatement()) {
        ResultSet rs = stmt.executeQuery(query);

        while (rs.next()) {
            System.out.println(
                rs.getString("COF_NAME") + ", " +
                rs.getInt("SUP_ID") + ", " +
                rs.getFloat("PRICE") + ", " +
                rs.getInt("SALES") + ", " +
                rs.getInt("TOTAL")
            );
        }
    } catch (SQLException e) {
        e.printStackTrace(); // 实际项目中建议写日志或提示用户
    }
}

📌 这个例子用 try-with-resources 自动关闭 JDBC 的 Statement 对象,干净利落!


🧩 实用贴士

提示内容
✅ 推荐使用所有实现了 AutoCloseable 的资源都应该用这个语法
🚫 不可变try 中声明的变量是隐式 final,不能再赋值
📌 可选 finally可以同时加上 catchfinally,逻辑更完整
🧼 清洁顺序最后创建的资源会最先关闭(类似栈结构)
❗ 兼容性要求只能在 Java 7 及以上使用

  • “你再也不用担心忘了关文件了,Java 自动帮你清理!”
  • “try-with-resources 是写 IO、数据库访问时的标配姿势。”
  • “多个资源按顺序声明,Java 会自动逆序关闭它们,非常优雅。”
  • “finally 中的异常可能覆盖真实错误,但 try-with-resources 会保留更多上下文!”

📌 总结:为什么用 try-with-resources?

优点描述
🔒 安全自动释放资源,防止泄漏
🧼 简洁不需要手写 finally,代码更清晰
🤝 灵活支持多个资源,支持 catch/finally
🚫 少错更容易写出正确的关闭逻辑