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.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文には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などの専用化された例外をスローしたり、例外をまったくスローしないようにしたりできます。