Try-with-resources は Java の IO ストリームを自動的に閉じます

    従来の入出力ストリーム処理では、一般的に使用される構造は次のとおりです。try-catch-finally 構造は、関連する例外をキャプチャするために使用されます。最後に、例外があるかどうかに関係なく、ストリームを閉じます。

try {
  //todo
} catch (IOException e) {
    log.error("read xxx fail,{}", e.getMessage())
} finally {
    try {
        if (in != null)in.close();
        if (out != null)out.close();
    } catch(Exception e) {
        log.error("stream close error,{}", e.getMessage())
    }
}

     jdk1.7 以降では、ストリームを自動的に閉じることができる try() {} catch(IOException e){} を使用して io ストリームを処理することをお勧めします。以下に示すのは、ファイルの内容を 1 行ずつ読み取る簡単な例です。

package com.xxx.io;

import java.io.FileNotFoundException;
import java.nio.file.Paths;
import java.util.Scanner;

public class ScannerDemo {
    public static void main(String[] args) {
        String filePath = "conf/test.txt";
        try (Scanner scanner = new Scanner(Paths.get(filePath).toFile())) {
            String line;
            while (scanner.hasNextLine()) {
                line = scanner.nextLine();
                System.out.println(line);
            }
        } catch (FileNotFoundException e) {
            System.out.println("read file error : " + e.getMessage());
        }
    }
}

    追跡とデバッグが可能です。try(){} の実行が終了すると、scanner.close() メソッド本体に入ります。 

     try(){} コード ブロックを使用した後、コードの実行が完了した後、ストリームを自動的に閉じることができます。これは従来の方法よりもはるかに簡単です。

    try() 部分には、セミコロンで区切られた複数のステートメントを含めることも、入力ストリームと出力ストリームの両方を含めることもできます。最後に、実行は完了し、一律に閉じられます。

    いくつかの記事では、これはさまざまなストリームが AutoCloseable インターフェイスを実装し、close() メソッドを実装しているためであると述べられていましたが、実際、先ほど実装した Scanner クラスは AutoCloseable を実装せず、Closeable インターフェイスのみを実装しました。

    次の例では、クラスをカスタマイズし、Closeable インターフェイスを実装し、close() メソッドをオーバーライドします。

package com.xxx.io;

import java.io.Closeable;

public class AutoCloseTest implements Closeable {
    @Override
    public void close() {
        System.out.println("closed");
    }

    public void work() {
        System.out.println("work");
    }

    public static void main(String[] args) {
        try (AutoCloseTest test = new AutoCloseTest()){
            test.work();
        }
    }
}

    プログラムを実行すると、最終的に出力される結果は次のようになります。

 

    同様に、try(){} を実行した後、ストリームの close() メソッドが実行されます。

    その理由は、コンパイラがこのコードをコンパイルした後、生成されるコードは実際には従来の try{}catch()finally{} 構造に似ているためです。

 

    つまり、コード try(){} は実際には try(){}catch()finally{} の短縮形です。ストリームが自動的に閉じるのは、それほど魔法のようなものではないようです。

    もう 1 つの質問があります。ここのコード ブロック内の try(){} だけが例外をキャッチしません。最終コードがコンパイルされた後、キャッチ例外が追加されます。コードにキャッチ例外がある場合、それは原因ではありませんか?例外情報は失われますか? 実際には、いいえ、今コンパイルしたスキャナーのサンプルの結果を見てみましょう。

    ここで try(){} がコンパイルされた後、例外がキャッチされた場合は addSuppressed() オペレーションが実行され、外側の try{}catch{} は引き続き例外をキャッチできます。

おすすめ

転載: blog.csdn.net/feinifi/article/details/131075463