# try-with-resources 声明 > 原文: [https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html](https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html) `try` -with-resources 语句是声明一个或多个资源的`try`语句。*资源*是一个在程序完成后必须关闭的对象。 `try` -with-resources 语句确保在语句结束时关闭每个资源。实现`java.lang.AutoCloseable`的任何对象(包括实现`java.io.Closeable`的所有对象)都可以用作资源。 以下示例从文件中读取第一行。它使用`BufferedReader`实例从文件中读取数据。 `BufferedReader`是程序完成后必须关闭的资源: ```java static String readFirstLineFromFile(String path) throws IOException { try (BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } } ``` 在此示例中,`try` -with-resources 语句中声明的资源是`BufferedReader`。声明语句出现在`try`关键字后面的括号内。 Java SE 7 及更高版本中的类`BufferedReader`实现了接口`java.lang.AutoCloseable`。因为`BufferedReader`实例在`try` -with-resource 语句中声明,所以无论`try`语句是正常还是突然完成(由于方法`BufferedReader.readLine`抛出`IOException`),它都将被关闭)。 在 Java SE 7 之前,无论`try`语句是正常还是突然完成,您都可以使用`finally`块来确保关闭资源。以下示例使用`finally`块而不是`try` -with-resources 语句: ```java 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`块抛出的异常;从`try`块抛出的异常被抑制。相反,在示例`readFirstLineFromFile`中,如果从`try`块和`try` -with-resources 语句抛出异常,则方法`readFirstLineFromFile`抛出从`try`块抛出的异常;从`try` -with-resources 块抛出的异常被抑制。在 Java SE 7 及更高版本中,您可以检索已抑制的异常;有关详细信息,请参阅[禁止异常](#suppressed-exceptions)部分。 您可以在`try` -with-resources 语句中声明一个或多个资源。以下示例检索 zip 文件`zipFileName`中打包的文件的名称,并创建包含这些文件名称的文本文件: ```java public static void writeToFileZipFileContents(String zipFileName, String outputFileName) throws java.io.IOException { java.nio.charset.Charset charset = java.nio.charset.StandardCharsets.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()); } } } ``` 在此示例中,`try` -with-resources 语句包含两个以分号分隔的声明:`ZipFile`和`BufferedWriter`。当直接跟随它的代码块正常或由于异常终止时,`BufferedWriter`和`ZipFile`对象的`close`方法将按此顺序自动调用。请注意,资源的`close`方法在它们创建的*相反*顺序中调用。 以下示例使用`try` -with-resources 语句自动关闭`java.sql.Statement`对象: ```java 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`是 JDBC 4.1 及更高版本 API 的一部分。 **注**:`try` -with-resources 语句可以使`catch`和`finally`块像普通的`try`语句一样。在`try` -with-resources 语句中,任何`catch`或`finally`块在声明的资源关闭后运行。 可以从与`try` -with-resources 语句关联的代码块中抛出异常。在示例`writeToFileZipFileContents`中,可以从`try`块抛出异常,当`try` -with-resources 语句尝试关闭`ZipFile`和`BufferedWriter`时,最多可以抛出两个异常。对象。如果从`try`块抛出异常并且从`try` -with-resources 语句抛出一个或多个异常,那么从`try` -with-resources 语句抛出的那些异常将被抑制,并抛出异常块是由`writeToFileZipFileContents`方法抛出的块。您可以通过从`try`块抛出的异常中调用`Throwable.getSuppressed`方法来检索这些抑制的异常。 ## 实现 AutoCloseable 或 Closeable 接口的类 请参阅 [`AutoCloseable`](https://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html) 和 [`Closeable`](https://docs.oracle.com/javase/8/docs/api/java/io/Closeable.html) 接口的 Javadoc,以获取实现这些接口之一的类列表。 `Closeable`接口扩展了`AutoCloseable`接口。 `Closeable`接口的`close`方法抛出`IOException`类型的异常,而`AutoCloseable`接口的`close`方法抛出`Exception`类型的异常。因此,`AutoCloseable`接口的子类可以覆盖`close`方法的这种行为,以抛出专门的异常,例如`IOException`,或者根本没有异常。