try-with-resources語句是一個聲明一個或多個資源的 try 語句。一個資源做爲一個對象,必須在程序結束以後隨之關閉。 try-with-resources語句確保在語句的最後每一個資源都被關閉 。任何實現了 java.lang.AutoCloseable的對象, 包括全部實現了 java.io.Closeable 的對象, 均可以用做一個資源。 html
下面的例子讀取文件的第一行。它使用了 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),BufferedReader都將會關閉。 sql
在 Java SE 7以前, 可使用 finally 塊來確保資源被關閉,無論 try 語句正常地完成或是發生意外。下面的例子使用 finally 塊替換 try-with-resources 語句: api
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。 oracle
能夠在一個 try-with-resources 語句中聲明一個或多個資源。下面的例子檢索zip文件 zipFileName 中全部文件的名稱並建立一個包含那些文件名稱的文本文件: ide
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()); } } }
在這個例子中, try-with-resources 語句包含兩個由分號隔開的聲明: ZipFile 和 BufferedWriter。當代碼塊直接伴隨着它正常地或因爲一個異常終止時, BufferedWriter 和 ZipFile 對象的 close 方法以這種順序自動地調用 。注意:資源的 close 方法調用順序與它們的建立順序相反。 ui
下面的例子使用一個 try-with-resources 語句來自動關閉一個 java.sql.Statement 對象: spa
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的一部分。 code
注意: 一個 try-with-resources 語句能夠像普通的 try 語句那樣有 catch 和 finally 塊。在try-with-resources 語句中, 任意的 catch 或者 finally 塊都是在聲明的資源被關閉之後才運行。 htm
與 try-with-resources 語句關聯的代碼塊可能會拋出異常。在 writeToFileZipFileContents這個例子中, 當試圖關閉 ZipFile 和 BufferedWriter 對象時,try 塊可能會拋出一個異常,而且 try-with-resources 語句可能拋出多達兩個異常 。若是 try 塊拋出異常而且 try-with-resources 語句拋出一個或多個異常,那麼從 try-with-resources 語句中拋出的異常將會被抑制, 而且塊拋出的異常是由 writeToFileZipFileContents 方法拋出的那一個。你能夠經過調用由 try塊拋出的異常的Throwable.getSuppressed 方法檢索這些被抑制的異常信息。
參見 AutoCloseable 和 Closeable 接口的Javadoc能夠看到實現了二者當中的任何一個接口的類集。Closeable 接口繼承了 AutoCloseable 接口。 Closeable接口的 close 方法拋出IOException 類型的異常而 AutoCloseable 接口的 close 方法拋出 Exception 類型的異常。所以, subclasses of the AutoCloseable 接口的子類能夠重寫 close 方法的這個行爲來拋出指定的異常,例如 IOException, 或者沒有異常。