はじめに:try-with-resourcesって何が便利なの?
Javaでファイルを開いたり、データベースに接続したりすると、**「使い終わったら閉じる」**という作業が必ず必要になります。
この「閉じ忘れ」がバグやメモリリークの原因になります。
そこで登場したのが、try-with-resources構文。
これはJava 7以降で導入されたもので、リソースを自動的に閉じてくれる便利な機能です。
でもその裏で「本当は何が起きているの?」
今回は、初心者にもわかるように、その仕組みをやさしく説明します。
1. 「リソース」ってなに?
リソースとは、プログラムが一時的に使う外部の資源のことです。
例:
- ファイル(
FileReader,BufferedReader) - データベース接続(
Connection,ResultSet) - ネットワーク(
Socket)
こういったものは、使い終わったら必ず閉じる必要があります。
閉じないと、メモリを消費し続けたり、他のプログラムと衝突したりします。
2. これまでの書き方と問題点
昔のJavaでは、こんなふうに書いていました。
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以降なら、こんなふうに書けます。
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構文に自動変換しています。
try (BufferedReader br = new BufferedReader(new FileReader("data.txt"))) {
String line = br.readLine();
}
この1文は、実際には次のような処理を自動で行っています:
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. 複数リソースのクローズ順序にも秘密がある
try (
ResourceA a = new ResourceA();
ResourceB b = new ResourceB()
) {
// 使用処理
}
この場合、クローズの順番は逆になります:
b.close()a.close()
これは「最後に作られたものから先に閉じる」というルールです。
6. Java 9からさらに便利に!
Java 9からは、try-with-resourcesで既に作成済みのリソースを使うこともできます。
BufferedReader br = new BufferedReader(new FileReader("data.txt"));
try (br) {
String line = br.readLine();
}
変数brが**実質的にfinal(再代入されない)**ならOK。コードがよりすっきり書けます!
7. suppressed例外とは?
close()中にエラーが起きても、それを上書きせず、tryブロック中の例外が優先されます。
その際、close()中の例外はsuppressed exceptionとして記録されます。
確認する方法:
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の理解を深めたい
- 転職に強くなりたい
という方は、サイゼントアカデミー があなたをサポートします!


コメント