try
-with-resources 文は、1 つ以上のリソースを宣言する try
文です。リソースは、プログラムでの使用が終わったら閉じられなければいけないオブジェクトです。try
-with-resources 文は、文の終わりで各リソースが確実に閉じられるようにします。java.io.Closeable
を実装しているすべてのオブジェクトも含め、java.lang.AutoCloseable
インタフェースを実装しているオブジェクトはリソースとして使用できます。
次の例は、ファイルから最初の行を読み取ります。ファイルからデータを読み取るために BufferedReader
のインスタンスを使用します。BufferedReader
は、プログラムでの使用が終わったら閉じられなければいけないリソースです。
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
ブロックを使用できます。次の例では、try
-with-resources 文の代わりに 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
ブロックからスローされた例外をスローします。try
ブロックからスローされた例外は抑制されます。これに対し、readFirstLineFromFile
の例では、try
ブロックと try
-with-resources 文の両方から例外がスローされた場合、メソッド readFirstLineFromFile
は try
ブロックからスローされた例外をスローします。try
-with-resources ブロックからスローされた例外は抑制されます。Java SE 7 以降では、抑制された例外を取得できます。詳細は、「抑制された例外」を参照してください。
1 つの try
-with-resources 文で 1 つ以上のリソースを宣言できます。次の例は、Zip ファイル zipFileName
にパッケージ化されているファイルの名前を取得し、これらのファイル名を含むテキストファイルを作成します。
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 文には 2 つの宣言 ZipFile
および BufferedWriter
が含まれており、セミコロンで区切られています。その直後のコードブロックが正常に終了または例外によって終了した場合、BufferedWriter
オブジェクトと ZipFile
オブジェクトの close
メソッドが、この順序で自動的に呼び出されます。リソースの close
メソッドは、作成時とは逆の順序で呼び出されます。
次の例では 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
は、JDBC 4.1 以降の API の一部です。
注:通常の try
文と同様に、try
-with-resources 文には catch
ブロックと finally
ブロックを含めることができます。try
-with-resources 文内の catch
または finally
ブロックは、宣言されているリソースが閉じられたあとで実行されます。
try
-with-resources 文に関連付けられたコードブロックから例外がスローされる場合があります。writeToFileZipFileContents
の例では、try
ブロックからは例外が 1 つスローされる可能性があり、try
-with-resources 文からは、ZipFile
オブジェクトと BufferedWriter
オブジェクトを閉じようとするときに最大 2 つの例外がスローされる可能性があります。try
ブロックから例外が 1 つスローされ、try
-with-resources 文から 1 つ以上の例外がスローされた場合、try
-with-resources 文からスローされた例外は抑制され、ブロックからスローされた例外が writeToFileZipFileContents
メソッドによってスローされます。これらの抑制された例外は、try
ブロックからスローされた例外から Throwable.getSuppressed
メソッドを呼び出すことで取得できます。
AutoCloseable
または Closeable
インタフェースを実装するクラスのリストについては、これらのインタフェースの Javadoc を参照してください。Closeable
インタフェースは AutoCloseable
インタフェースを拡張したものです。Closeable
インタフェースの close
メソッドは IOException
型の例外をスローし、AutoCloseable
インタフェースの close
メソッドは Exception
型の例外をスローします。その結果、AutoCloseable
インタフェースのサブクラスでは close
メソッドのこの動作をオーバーライドして、IOException
などの専用化された例外をスローしたり、例外をまったくスローしないようにしたりできます。