PR

Java:try-with-resources文の基本を1からわかりやすく

Java

Javaでファイル操作やデータベース接続などを行う際は、リソースを使い終わったら必ず解放(close)する必要があります。従来はtry-catch-finally参考 Javaの例外処理)で処理とクローズをしっかり書かなければなりませんでしたが、Java 7から導入されたtry-with-resources構文を使えば、コードが驚くほどシンプルになります。

このページではJava初心者向けに1からわかりやすくサンプルコード付きでご説明します。

スポンサーリンク

try-with-resources文の基本

try-with-resourcesは、tryブロックで宣言したリソースを自動的にclose()してくれる構文です。以下の特徴があります。

try (リソースの宣言) {
    // リソースを使った処理
} catch (例外クラス 変数) {
    // 例外発生時の処理
}
  1. try丸括弧 ( ) 内でリソースを宣言 する。
  2. リソースは AutoCloseable インタフェースを実装している必要がある。(例:BufferedReader, FileWriter, Connection など)
  3. try ブロックの処理が終了すると、自動的に close() メソッドが呼び出される
  4. catch ブロックを省略することも可能。(ただし、例外処理が不要な場合のみ)
  5. 複数のリソースを ; で区切って宣言できる
  • リソース解放のコードが不要
    tryブロックを抜けると、自動的にclose()が呼び出されます。
  • コードがスッキリ
    finallyブロックを書かなくても良いので、可読性が高まります。
  • 複数リソースも一括管理
    ;で区切ってリソースを並べれば、すべて自動でクローズされます。
try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
} catch (IOException e) {
    e.printStackTrace();
}

try( )の中でインスタンスを宣言するだけで、tryブロックを抜ける際に自動でclose()されます。

また、以下のように複数のリソースを同時に使うような処理も記述可能です。

try (
    BufferedReader br = new BufferedReader(new FileReader("input.txt"));
    BufferedWriter bw = new BufferedWriter(new FileWriter("output.txt"))
) {
    String line;
    while ((line = br.readLine()) != null) {
        bw.write(line);
        bw.newLine();
    }
} catch (IOException e) {
    e.printStackTrace();
}

読み取り用と書き込み用の両方を一括で管理できます。複数のリソースが増えてもスッキリしたコードになります。

裏側の仕組み(AutoCloseableインタフェース)

try-with-resources構文では、AutoCloseableインタフェース(またはそのサブインタフェースであるCloseableなど)を実装したクラスのみが自動でクローズされます。標準のファイル操作系クラスはすでにCloseableを実装しているため、そのまま使えます。

もし自作クラスで同じ仕組みを使いたい場合は、以下のようにAutoCloseableを実装してください。

class MyResource implements AutoCloseable {
    @Override
    public void close() throws Exception {
        // リソース解放処理
    }
}

これでtry-with-resourcesの括弧内に書くだけで、自動クローズ対象にできます。

例外の抑制(Suppressed Exception)

try-with-resourcesでは、tryブロック内で起きた例外と、close()処理中に起きた例外が同時に発生した場合、後者は抑制(Suppressed)され、前者の例外オブジェクトに紐づきます。

  • 実際に問題の原因となったメインの例外が最初にわかる
  • 抑制された例外はgetSuppressed()で取り出せる

これにより、例外の管理がより安全かつわかりやすくなっています。

旧来の書き方との比較

try-catch-finallyの場合

BufferedReader br = null;
try {
    br = new BufferedReader(new FileReader("test.txt"));
    // ...
} catch (IOException e) {
    // ...
} finally {
    if (br != null) {
        try {
            br.close();
        } catch (IOException e) {
            // ...
        }
    }
}

try-with-resourcesの場合

try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
    // ...
} catch (IOException e) {
    // ...
}

同じ処理内容でも、不要なクローズ処理が書かれなくて済むためスッキリ見えます。

ポイント try-with-resources と従来の方法の違い

比較項目try-with-resourcestry-catch-finally
リソースの解放自動で close() を呼ぶfinally ブロックで手動で close() する必要がある
コードの簡潔さ短くてシンプルネストが深く、冗長
複数リソースの管理; で区切るだけfinally でそれぞれ null チェックしながら close() する必要あり
例外処理try のブロックを抜けると確実に close() されるfinally 内で close() による例外をキャッチする必要あり

FAQ どちらを使うべきか?

Java 7以降なら try-with-resources を推奨
AutoCloseable を実装しているリソースなら、明示的に close() する必要がないため、可読性・保守性が向上する。

古いバージョンのJava(6以前)を使う場合は try-catch-finally
→ Java 6以前では try-with-resources は使えないため、従来の方法を採用するしかない。

AutoCloseable を実装していないカスタムリソースの場合
try-catch-finally を使うか、自作クラスを AutoCloseable に対応させる。

JDBCでの利用例

ファイル操作だけでなく、データベース操作でも非常に便利です。

try (
    Connection conn = DriverManager.getConnection("jdbc:mysql://localhost/test", "user", "password");
    Statement stmt = conn.createStatement();
    ResultSet rs = stmt.executeQuery("SELECT * FROM sample_table")
) {
    while (rs.next()) {
        System.out.println(rs.getString("name"));
    }
} catch (SQLException e) {
    e.printStackTrace();
}

Connection, Statement, ResultSetのように複数のリソースをまとめて安全にクローズできるため、コーディング効率が大幅にアップします。

まとめ Java:try-with-resources文

  • リソースの自動クローズで手間を削減
    close()の呼び出し漏れや例外処理の複雑化を防げます。
  • 複数リソースも一気に管理
    ;で区切るだけでOK。コードがさらにシンプルに。
  • 例外の抑制機能
    複数例外が発生してもメインの例外が優先され、補足的な例外は抑制されます。

Java 7以降であれば標準で利用できる構文です。今でもJavaの現場で多く使われていますので、これを機にぜひマスターして、より快適な開発環境を整えていきましょう。

タイトルとURLをコピーしました