0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

try-with-resources文

Last updated at Posted at 2025-06-16

概要

1つ以上の「使い終わったらクローズする必要があるオブジェクト」を受け取ったtry文のこと。

例1(単独宣言時)
try(BufferedReader br = new BufferedReader(new FileReader(path))){

複数宣言の際は、宣言同士をセミコロン;で区切る必要あり。

例2(複数宣言時)
try(
    java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName);
    java.io.BufferedWriter bw = java.nio.file.Files.newBufferedWriter(outputFilePath, charset)
){

特徴

try-with-resources句(冒頭の()内の記述)で宣言されたインスタンスは、
try句内で例外が発生したか否か、catch句で例外が補足されたかどうかに関わらず、常にクローズされる。

クローズの際は、渡した順番と逆の順序で、処理が呼び出される。
例2の場合なら、BufferedWriterのcloseメソッド⇒ZipFileのcloseメソッド、の順となる。

使用上の注意①:対象のクラスについて

対象のクラスが、インタフェースjava.lang.AutoCloseableを実装していないと、try-with-resources文に用いることはできないため注意。

実際には、以下のようなクラスがtry-with-resources文の対象としてよく用いられます。

  • BufferedReader / BufferedWriter … テキストファイルの読み書き
  • FileInputStream / FileOutputStream … バイナリファイルの読み書き
  • ZipFile … ZIPファイル操作
  • Connection, Statement, ResultSet(JDBC)… データベース操作
  • Files.newBufferedReader / newBufferedWriter(NIO)… ファイル入出力

これらはいずれも AutoCloseable または Closeable を実装しており、
明示的なクローズ処理が必要なリソースです。

おまけ(try-with-resources文で利用できるカスタムクラス例)

  • インタフェースの実装(implements AutoCloseable)
  • クローズ時処理をオーバーライドで実装
public class Main {
  public static void main(String[] args) {
    test t = null;
    t = new test("test1");
    try(t){
        t.doSomething();
    }catch(Exception e){
      e.printStackTrace();
    }
  }

  public static class test implements AutoCloseable{
    private final String name;
    test(String name){
        this.name = name;
        System.out.println(name + " created");
    }
    public void doSomething(){
      System.out.println(name + " doing something");
    }
    @Override
    public void close(){
      System.out.println(name + " closed");
    }
  }
}

使用上の注意②:対象の宣言について

Javaのバージョンにより、対象の宣言に制限が生まれる。

  • Java7または8
    try-with-resources句にて宣言しなければならない。
    つまり、事前に宣言されていた変数を引数として渡したとしても、例外が発生する。
NG例(in Java7または8)
BufferedReader br = new BufferedReader(new FileReader(path));
try(br){
  • Java9以降
    事前に宣言済みである変数も、活用できるようになった。公式アップデート内容通知ページ
    つまり先程のNG例のような記述でも、問題なく処理される。
    ただし、変数が必ずtry-with-resources句内で宣言されるわけではなくなったことで、
    final変数・実質的final変数、いずれでもない変数を対象として指定される可能性が出てきたが、その場合は例外が発生する。
NG例(in Java9以降)
BufferedReader br = null;
br = new BufferedReader(new FileReader(path))
try(br){

実質的final変数
final修飾されていないものの、初回代入以来一度も値が変更されていない変数のこと。

通常のtry文(finally句使用)との違い

  • finally句でクローズ処理を記述したりする必要がなくなる
    • より短く記述できるようになる他、クローズ処理記述忘れによるトラブルも抑止できる、というメリットがある。

  • 例外が複数個所にて発生した場合の挙動が異なる
    • 通常のtry文
      try句・finally句の両方において例外が発生した場合、finally句で発生した例外が優先され、try句で発生した例外は失われることがある。
    • try-with-resources文
      try-with-resource句とtry句の両方において例外が発生した場合、
      try句で発生した例外のみ 主例外(primary exception) としてスローされ、
      try-with-resources句で発生した例外は 抑制例外(suppressed exception) となりスローはされないものの、補助的に記録はされる。
      • try-with-resources句で発生した抑制例外は、try句よりスローされた例外でThrowable.getSuppressedメソッドを呼び出すことにより、取得することが可能。

実行順序詳細

  • 例外が発生しない場合
    try句 → クローズ → finally句
  • 例外が発生した場合
    try句 → catch句 → クローズ → finally句

まとめ

try-with-resources文は、上記のような性質により、例外処理の信頼性・コードの可読性を向上させることができる。
ファイル操作・DB接続・ソケット通信など、明示的クローズが必須な処理を作成する際は、こちらを採用するとよいかもしれない。


参照

try-with-resources文公式ドキュメント

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?