Javaでファイル操作やデータベース接続などを行う際は、リソースを使い終わったら必ず解放(close)する必要があります。従来はtry-catch-finally
(参考 Javaの例外処理)で行いたい処理に加えてclose処理をしっかり書かなければなりませんでしたが、Java 7から導入されたtry-with-resources構文を使えば、コードをシンプルにしつつ、安全な処理を実現することができます。
昔からあるシステムのコードではあまり見かけませんが、直近新規で開発されたシステムなどでは見るシーンも増えました。Java Silver試験でも出題される内容ですので、頭に入れておきたい基本知識の1つです。

このページではJava初心者向けに1からわかりやすくサンプルコード付きでご説明します。
try-with-resources文
try-with-resourcesは、try
ブロックで宣言したリソースを自動的にclose()
してくれる構文です。以下の特徴があります。
- リソース解放のコードが不要
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
など)を実装したクラスのみが自動でクローズされます。
参考 インターフェースとは?
もし自作クラスで同じ仕組みを使いたい場合には、以下のようにAutoCloseable
を実装する必要があります。これでtry-with-resources
の括弧内に書くだけで、自動クローズ対象にできます。
class MyResource implements AutoCloseable { @Override public void close() throws Exception { // リソース解放処理 } }
リソースを自動で閉じたいなら AutoCloseable を実装する
念のため再度念押ししておくと、Javaの try-with-resources
文は、一言でいうと自動で close() を呼んでくれる構文です。そして、これを適切に使うにはそのクラスが AutoCloseable
または Closeable
を実装している必要があります。
◆ 詳細:2つのインターフェースの違いと使い分け
インターフェース名 | close() の例外 | 主な用途 | Javaバージョン |
---|---|---|---|
Closeable | IOException | ファイルやストリーム処理 | Java 1.5 |
AutoCloseable | Exception | 全般的なリソース | Java 1.7 |
Closeable
はIOException
をスローする想定なので、主に 入出力系(IO) に特化。AutoCloseable
はより汎用的で、どんなリソースでも自動で閉じたい時に使える。Closeable
はAutoCloseable
の一種と考えてOK。
class MyResource implements AutoCloseable { public void doSomething() { System.out.println("リソース使ってるよ"); } @Override public void close() { System.out.println("リソース閉じたよ"); } } public class Main { public static void main(String[] args) { try (MyResource res = new MyResource()) { res.doSomething(); } } } // 出力: // リソース使ってるよ // リソース閉じたよ
- Qtry-with-resourcesはどういう仕組みでcloseしているの?
- A
◆ 結論:実はコンパイル時に「
finally
でclose()
を呼ぶコード」に変換されています。try-with-resources
は 構文上の糖衣構文(シンタックスシュガー) で、コンパイラが裏でfinally
によるclose()
呼び出しに展開してくれています。
例えば次のコード:
try (MyResource res = new MyResource()) { res.doSomething(); }
これはコンパイルされると、以下のような構造に変換されます:
MyResource res = new MyResource(); Throwable primaryException = null; try { res.doSomething(); } catch (Throwable t) { primaryException = t; throw t; } finally { if (res != null) { if (primaryException != null) { try { res.close(); } catch (Throwable closeException) { primaryException.addSuppressed(closeException); } } else { res.close(); } } }
ポイント | 説明 |
---|---|
null チェック | 例外が出ても close() を呼ぶために必須 |
addSuppressed() | もし close() でも例外が出たら、もとの例外に「抑制例外」として記録する |
Throwable | Exception よりも広くキャッチして、エラーも含めたあらゆる異常を扱える |

try-with-resources
はコンパイル時にtry-catch-finally
に展開されている。- 複数の例外(処理中+クローズ時)もきちんと扱えるようになっている。
- 実は「しっかりした例外処理」が自動で入ってるのが便利なポイント。
気になるなら、.class
を javap -c
で逆アセンブルしてみるのもおすすめです!
try-with-resources は 自動で close() を「呼ぶ」だけ
Javaの try-with-resources
は便利ですが、リソースの解放処理自体はあなた(開発者)が close()
メソッド内に実装しないと意味がありません。
◆ 例:ちゃんと書かないと何も閉じられない
class MyResource implements AutoCloseable { @Override public void close() { // ここにリソース解放処理を書かないとダメ System.out.println("閉じました!"); } }
もし close()
の中が空だったら、「呼ばれてるけど何もしてない」状態になります。そのため、以下のようなメソッドを利用して必ずクローズする処理を記述しなければいけません。(この点、JavaSilverだけで勉強していると誤解しがちですので、注意が必要です。)
- ファイルを開いているなら →
fileStream.close()
- DB接続なら →
connection.close()
- スレッドやプロセスを使ってるなら →
shutdown()
など
質問 | 答え |
---|---|
close() は自動で呼ばれる? | はい。try-with-resources により自動で呼ばれます。 |
処理内容は書く必要ある? | 絶対に必要。何を閉じるかは自分で記述します。 |
書かなかったら? | 呼ばれるけど、何も起きません(リソースは解放されない)。 |
旧来の書き方との比較
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-resources | try-catch-finally |
---|---|---|
リソースの解放 | 自動で close() を呼ぶ | finally ブロックで手動で close() する必要がある |
コードの簡潔さ | 短くてシンプル | ネストが深く、冗長 |
複数リソースの管理 | ; で区切るだけ | finally でそれぞれ null チェックしながら close() する必要あり |
例外処理 | try のブロックを抜けると確実に close() される | finally 内で close() による例外をキャッチする必要あり |
どちらを使うべきか?
✅ 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
のように複数のリソースをまとめて安全にクローズできるため、コーディング効率が大幅にアップします。