java7新特性之Try-with-resources statement

本文详细介绍了Java中try-with-resources语句的使用方法及其优势。通过具体的代码示例,展示了如何利用这一特性自动关闭资源,简化异常处理逻辑,并提高代码的健壮性和可维护性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

try-with-resources 语句是一个声明了1到多个资源的try语句。资源是指这个try执行完成后必需close掉的对象,比如connection, resultset等。

try-with-resources 语句会确保在try语句结束时关闭所有资源。实现了java.lang.AutoCloseablejava.io.Closeable的对象都可以做为资源。

下面是一个例子,它会从一个文件中读出首行文本,这里使用了BufferedReader 的实例来读取数据,BufferedReader 是一个资源,它应该在程序完成时被关闭。

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

在这个例子里面,资源是一个BufferedReader, 声明语句是在try后面的括号内。在java7或更晚的版本中,BufferedReader实现了java.lang.AutoCloseable接口。由于BufferedReader被定义在try-with-resource 语句中,因此不管try代码块是正常完成或是出现异常,这个BufferedReader 的实例都将被关闭。

在java7之前的版本中,你可以使用finally 代码块来确保资源被关闭(不管try正常完成还是出现异常)。下面是使用finally的例子:

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

 

然而,在这里例子里面,如果readLine方法和close方法都抛出了异常,readFirstLineFromFileWithFinallyBlock 方法只能抛出finally代码块里面的异常,也就是close方法出现的异常,try代码块里面的异常被禁止;相反,在readFirstLineFromFile这个例子中,如果try 代码块和try-with-resources 语句都出现异常,readFirstLineFromFile 方法将出抛出来自try代码块的异常,从try-with-resources抛出的异常被禁止。在java7或更晚的版本中,我们可以获取到这些被禁止的异常。

你可以声明1到多个资源,看下面的例子

public static void writeToFileZipFileContents(String zipFileName, String outputFileName)
    throws java.io.IOException {

    java.nio.charset.Charset charset = java.nio.charset.Charset.forName("US-ASCII");
    java.nio.file.Path outputFilePath = java.nio.file.Paths.get(outputFileName);

    // Open zip file and create output file with try-with-resources statement

    try (
      java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName);
      java.io.BufferedWriter writer = java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
    ) {

      // Enumerate each entry

      for (java.util.Enumeration entries = zf.entries(); entries.hasMoreElements();) {

        // Get the entry name and write it to the output file

        String newLine = System.getProperty("line.separator");
        String zipEntryName = ((java.util.zip.ZipEntry)entries.nextElement()).getName() + newLine;
        writer.write(zipEntryName, 0, zipEntryName.length());
      }
    }
  }


 

在这个例子中,有两个资源,资源之间用分号隔开。资源被关闭的顺序与它们被创建的顺序相反,也就是说writer 先被关闭,接着是zf。

 下面我们使用try-with-resources 语句自动关闭一个java.sql.Statement 对象:

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()) {
        String coffeeName = rs.getString("COF_NAME");
        int supplierID = rs.getInt("SUP_ID");
        float price = rs.getFloat("PRICE");
        int sales = rs.getInt("SALES");
        int total = rs.getInt("TOTAL");
        System.out.println(coffeeName + ", " + supplierID + ", " + price +
                           ", " + sales + ", " + total);
      }

    } catch (SQLException e) {
      JDBCTutorialUtilities.printSQLException(e);
    }
  }


这里的java.sql.Statement 是JDBC4.1或更晚的API的一部分。

注意:try-with-resources 也可以有catch和finally语句块,就像使用一个普通的try语句一样。在try-with-resources 语句中,catch或者finally将在资源被关闭后执行。

### `try-with-resources` 的基本用法 `try-with-resources` 是 Java 7 引入的一项特性,旨在简化资源管理。它确保在 `try` 块执行完毕后,所有声明为资源的变量都会被自动关闭,即使在操作过程中抛出异常也是如此[^3]。这种机制特别适用于需要手动关闭的资源,例如文件流、网络连接和数据库连接等。 #### 语法结构 `try-with-resources` 的基本语法如下: ```java try (ResourceType resource = new ResourceType()) { // 使用资源的代码 } catch (ExceptionType e) { // 处理异常的代码 } ``` 在 `try` 后的括号中声明并初始化资源,这些资源必须实现 `AutoCloseable` 接口,以便在 `try` 块结束时自动调用 `close()` 方法[^1]。 #### 示例 以下是一个使用 `try-with-resources` 关闭文件流的示例: ```java import java.io.FileInputStream; import java.io.IOException; public class TryWithResourcesExample { public static void main(String[] args) { try (FileInputStream fis = new FileInputStream("example.txt")) { int data; while ((data = fis.read()) != -1) { System.out.print((char) data); } } catch (IOException e) { e.printStackTrace(); } } } ``` 在这个示例中,`FileInputStream` 被声明在 `try` 的括号内,因此在 `try` 块执行完毕后,`FileInputStream` 会自动关闭,无需手动调用 `close()` 方法[^4]。 #### 多个资源的管理 `try-with-resources` 也支持同时管理多个资源。多个资源可以在 `try` 的括号内用分号分隔声明: ```java import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class MultipleResourcesExample { public static void main(String[] args) { try (FileReader fr = new FileReader("input.txt"); BufferedReader br = new BufferedReader(fr)) { String line; while ((line = br.readLine()) != null) { System.out.println(line); } } catch (IOException e) { e.printStackTrace(); } } } ``` 在这个示例中,`FileReader` 和 `BufferedReader` 都被声明在 `try` 的括号内,它们会在 `try` 块执行完毕后按声明顺序的逆序自动关闭[^2]。 #### 异常处理 如果在 `try` 块中发生异常,`try-with-resources` 会确保资源在异常处理之前关闭。此外,如果在关闭资源时也发生异常,这些异常会被抑制,可以通过 `Throwable.getSuppressed()` 方法获取。 ```java import java.io.FileInputStream; import java.io.IOException; public class ExceptionHandlingExample { public static void main(String[] args) { try (FileInputStream fis = new FileInputStream("example.txt")) { int data = fis.read(); System.out.print((char) data); } catch (IOException e) { e.printStackTrace(); // 获取被抑制的异常 for (Throwable t : e.getSuppressed()) { t.printStackTrace(); } } } } ``` 在这个示例中,如果 `read()` 方法抛出异常,`FileInputStream` 会自动关闭,而关闭过程中可能抛出的异常会被捕获并添加到主异常的抑制列表中[^2]。 ### `try-with-resources` 的优势 - **代码简洁性和清晰性**:资源的声明和关闭集中在一个 `try` 块中,避免了冗余的 `finally` 块[^2]。 - **防止资源泄漏**:即使在 `try` 块中抛出异常,资源也会被正确关闭,从而减少资源泄漏的风险。 - **异常堆栈管理**:在资源关闭过程中发生的异常会被抑制,主异常的堆栈信息得以保留,便于调试[^2]。 ### 应用场景 - **文件操作**:如读取或写入文件时,使用 `FileInputStream` 或 `FileOutputStream`。 - **网络连接**:如使用 `Socket` 或 `URLConnection` 时。 - **数据库连接**:如使用 `Connection` 或 `Statement` 时。 ### 注意事项 - **资源类型**:资源必须实现 `AutoCloseable` 接口,以便支持自动关闭。 - **多个资源的关闭顺序**:多个资源按声明顺序的逆序关闭,以避免依赖关系导致的问题。 - **嵌套资源管理**:可以将资源的声明嵌套在多个 `try-with-resources` 块中,以提高代码的可读性和维护性[^2]。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值