はじめに:try-with-resourcesって何が便利なの?
Javaでファイルを開いたり、データベースに接続したりすると、**「使い終わったら閉じる」**という作業が必ず必要になります。
この「閉じ忘れ」がバグやメモリリークの原因になります。
そこで登場したのが、try-with-resources構文。
これはJava 7以降で導入されたもので、リソースを自動的に閉じてくれる便利な機能です。
でもその裏で「本当は何が起きているの?」
今回は、初心者にもわかるように、その仕組みをやさしく説明します。
1. 「リソース」ってなに?
リソースとは、プログラムが一時的に使う外部の資源のことです。
例:
- ファイル(
FileReader
,BufferedReader
) - データベース接続(
Connection
,ResultSet
) - ネットワーク(
Socket
)
こういったものは、使い終わったら必ず閉じる必要があります。
閉じないと、メモリを消費し続けたり、他のプログラムと衝突したりします。
2. これまでの書き方と問題点
昔のJavaでは、こんなふうに書いていました。
1 2 3 4 5 6 7 8 9 10 |
BufferedReader br = null; try { br = new BufferedReader(new FileReader("data.txt")); String line = br.readLine(); } finally { if (br != null) { br.close(); } } |
これは一見良さそうに見えますが、
close()
自体がエラーになると、例外が上書きされる- 複数のリソースを扱うと書き方が複雑
finally
を忘れると「閉じ忘れ」が発生
という問題があります。
3. try-with-resourcesを使うとどうなる?
Java 7以降なら、こんなふうに書けます。
1 2 3 4 |
try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))) { String line = br.readLine(); } |
この1行で、brは自動で閉じられます!
面倒なfinally
も、null
チェックもいりません。
✔ 使えるリソースの条件
AutoCloseable
インターフェースを実装していること- 代表的なクラス:
BufferedReader
,InputStream
,Connection
, etc
4. 裏で何が起きている?try-with-resourcesの仕組み
Javaコンパイラ(javac)は、try-with-resources
を普通のtry-catch-finally
構文に自動変換しています。
1 2 3 4 |
try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))) { String line = br.readLine(); } |
この1文は、実際には次のような処理を自動で行っています:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
BufferedReader br = new BufferedReader(new FileReader("data.txt")); Throwable primaryException = null; try { String line = br.readLine(); } catch (Throwable t) { primaryException = t; throw t; } finally { if (br != null) { if (primaryException != null) { try { br.close(); } catch (Throwable closeException) { primaryException.addSuppressed(closeException); } } else { br.close(); } } } |
このように:
- 自動で
close()
が呼ばれる - 例外が重なった場合も、元の例外が優先される
- あとから出た例外は“抑制された例外(Suppressed Exception)”として記録される
5. 複数リソースのクローズ順序にも秘密がある
1 2 3 4 5 6 7 |
try ( ResourceA a = new ResourceA(); ResourceB b = new ResourceB() ) { // 使用処理 } |
この場合、クローズの順番は逆になります:
b.close()
a.close()
これは「最後に作られたものから先に閉じる」というルールです。
6. Java 9からさらに便利に!
Java 9からは、try-with-resources
で既に作成済みのリソースを使うこともできます。
1 2 3 4 5 |
BufferedReader br = new BufferedReader(new FileReader("data.txt")); try (br) { String line = br.readLine(); } |
変数br
が**実質的にfinal(再代入されない)**ならOK。コードがよりすっきり書けます!
7. suppressed例外とは?
close()
中にエラーが起きても、それを上書きせず、try
ブロック中の例外が優先されます。
その際、close()
中の例外はsuppressed exceptionとして記録されます。
確認する方法:
1 2 3 4 5 6 7 8 |
try { // try-with-resources処理 } catch (Exception e) { for (Throwable t : e.getSuppressed()) { t.printStackTrace(); } } |
8. よくある注意点
AutoCloseable
を実装していないクラスは使えないSystem.in
など、閉じると困るリソースは使わない方が良いcatch
がある場合も、finally
と同様に自動でclose()
が呼ばれるnull
のリソースをtry()
に入れるとNullPointerException
になる
9. まとめ:try-with-resourcesを正しく理解すれば、Javaの信頼性が上がる!
ポイント | 内容 |
---|---|
自動クローズ | close() を書かなくてOK |
例外の安全性 | 元の例外を優先、補助的な例外はsuppressed |
複数リソース対応 | クローズは逆順に自動実行 |
Java 9対応 | 既存リソースをtry で使える |
要件 | AutoCloseable 実装が必要 |
おわりに:try-with-resourcesを使いこなして、プロのコードに!
try-with-resourcesを知ることで、安全で効率的なリソース管理が自然にできるようになります。
これだけで「一歩上のJavaエンジニア」に近づけるはずです!
まずは、
👉 「絶対にJavaプログラマーになりたい人へ。」
で基本からしっかり学びましょう。
さらに、
- 例外処理が苦手
- Javaの理解を深めたい
- 転職に強くなりたい
という方は、サイゼントアカデミー があなたをサポートします!
コメント