Java で Try With Resource を使用する方法

Feb 21 2023
try-with-resource ステートメントを使用して例外を処理する方法 Java try with resource 構造 (別名 Java try-with-resources) は、Java InputStream や JDBC Connection などのリソースを使用し終わったときに自動的に閉じることができる例外処理メカニズムです。 。オラクルは、ネットワークソケット、データベース接続、ファイルやフォルダへの参照などのオブジェクトが使用後に完全に終了することを保証するために、2011 年に Try with resource 構文を Java 言語に追加しました。

try-with-resource ステートメントを使用して例外を処理する方法

Java のtry with resource構造 (別名Java try-with-resources ) は、Java InputStream や JDBC Connection などのリソースを使用し終わったときに自動的に閉じることができる例外処理メカニズムです。

オラクルは、ネットワークソケット、データベース接続、ファイルやフォルダへの参照などのオブジェクトが使用後に完全に終了することを保証するために、2011 年に Try with resource 構文を Java 言語に追加しました。開発者がこれらのリソースへのハンドルを開いた後にこれらのリソースを閉じないと、メモリ リークが発生し、回避可能なガベージ コレクション ルーチンがトリガーされ、サーバーの CPU に負担がかかる可能性があります。

· Java 7 より前
· try-with-resource ステートメントの使用方法?
·なぜ try-with-resource ステートメントを使用する必要があるのですか?
·例
·抑制された例外
· try-with-resources を使用する利点
·複数のリソースを使用した try-with-resources
· Java 9 — 実質的な最終変数

Java 7 より前

Java では、入力ストリームや出力ストリームなどのリソースを使用する場合、使用後に必ず閉じる必要があります。また、例外をスローする可能性があるため、 try-catchブロック内に置く必要があります。クロージングは​​finallyブロック内になければなりません。これは、少なくとも Java 7 までの方法です。これにはいくつかの欠点があります。

  • リソースを閉じる前に、リソースがnullかどうかを確認する必要があります
  • 終了自体で例外がスローされる可能性があるため、最終的には別のtry-catch を含める必要がありました。
  • プログラマーはリソースを閉じるのを忘れる傾向があります

try-with-resource ステートメントを使用するにはどうすればよいですか?

これは最初に Java 7 で導入されました。その背後にある全体的な考え方は、開発者が 1 つのtry-catch-finallyブロック内でのみ使用するリソースのリソース管理について心配する必要がないということでした。これは、開発者が実際にリソースを閉じるためにのみ使用していた、 finallyブロックの必要性を取り除くことで実現されます。

Java では、try-with-resources ステートメントは、1 つ以上のリソースを宣言する try ステートメントです。リソースは、プログラムの終了後に閉じる必要があるオブジェクトです。実行がtry-with-resourcesブロックを離れると、 try-with-resourcesブロック内から例外がスローされたかどうか、または閉じようとしたときに例外がスローされたかどうかに関係なく、try-with- resourcesブロック内で開かれたリソースはすべて自動的に閉じられます。リソース。

Java の try-with-resources 言語機能を使用するには、次のルールが適用されます。

  • try with resource ステートメントによって管理されるすべてのオブジェクトは、AutoCloseable インターフェイスを実装する必要があります。
  • Java の try with resource ブロック内で複数の AutoCloseable オブジェクトを作成できます。
  • try with resource ステートメントで宣言されたオブジェクトは、try ブロック内にスコープを持ちますが、catch ブロックとfinally ブロックにはスコープがありません。
  • try with resource ブロックで宣言されたオブジェクトの close() メソッドは、実行中に例外がスローされるかどうかに関係なく呼び出されます。
  • close() メソッドで例外がスローされた場合、その例外は抑制された例外として分類される可能性があります。

Try with resource ステートメントが使用されている場合、AutoCloseable オブジェクトによって参照されるリソースは常に閉じられ、一般にリソースの割り当てミスによって引き起こされる潜在的なメモリ リークが排除されます。

構文

try(declare resources here) {
    // use resources
}
catch(FileNotFoundException e) {
    // exception handling
}

簡単に言うと、自動的にクローズされるようにするには、リソースを try 内で宣言し、初期化する必要があります。

try (PrintWriter writer = new PrintWriter(new File("test.txt"))) {
    writer.println("Hello World");
}

新しいtry-with-resources機能を使用する簡単かつ明白な方法は、従来の冗長なtry-catch-finallyブロックを置き換えることです。

次のコードサンプルを比較してみましょう。

1 つ目は典型的なtry-catch-finally ブロックです。

Scanner scanner = null;
try {
    scanner = new Scanner(new File("test.txt"));
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException e) {
    e.printStackTrace();
} finally {
    if (scanner != null) {
        scanner.close();
    }
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy

try (Scanner scanner = new Scanner(new File("test.txt"))) {
    while (scanner.hasNext()) {
        System.out.println(scanner.nextLine());
    }
} catch (FileNotFoundException fnfe) {
    fnfe.printStackTrace();
}

例外に関しては、try-catch-finallyブロックと try-with-resources ブロックに違いがあります。try ブロックとfinally ブロックの両方で例外がスローされた場合、メソッドはfinally ブロックでスローされた例外を返します。

try-with-resources の場合、try ブロックと try-with-resources ステートメントで例外がスローされた場合、メソッドは try ブロックでスローされた例外を返します。try-with-resources によってスローされる例外は抑制されます。つまり、try-with-resources ブロックは抑制された例外をスローすると言えます。

try-with-resource ステートメントを使用する必要があるのはなぜですか?

try-with-resources ステートメントは、ステートメントの実行終了時に各リソースが確実に閉じられるようにします。リソースを閉じないと、リソース リークが発生する可能性があり、プログラムが利用可能なリソースを使い果たす可能性もあります。これは主にtry-catch-finallyブロックを使用するときに起こったことです

Java SE 7 より前では、finallyブロックを使用して、 tryステートメントが正常に完了したか突然完了したかに関係なく、リソースを確実に閉じることができました。次の例では、 try -with-resources ステートメントの代わりに、finallyブロックを使用します。

static String readFirstLineFromFileWithFinallyBlock(String path) throws IOException {
   
    FileReader fr = new FileReader(path);
    BufferedReader br = new BufferedReader(fr);
    try {
        return br.readLine();
    } finally {
        br.close();
        fr.close();
    }
}

この例では、readLineメソッドが例外をスローし、finallyブロック内のステートメントbr.close()が例外をスローした場合、FileReaderがリークしています。したがって、プログラムのリソースを閉じるには、finallyブロックの代わりにtry -with-resources ステートメントを使用してください。

例

次の例では、ファイルから最初の行を読み取ります。FileReaderとBufferedReaderのインスタンスを使用して、ファイルからデータを読み取ります。FileReaderとBufferedReader は、プログラムの終了後に閉じる必要があるリソースです。

import java.io.*;
class Main {
  public static void main(String[] args) {
    String line;
    try(BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
      while ((line = br.readLine()) != null) {
        System.out.println("Line =>"+line);
      }
    } catch (IOException e) {
      System.out.println("IOException in try block =>" + e.getMessage());
    }
  }
}

抑制された例外

try ブロックが例外をスローし、try-with-resources によって 1 つ以上の例外がスローされた場合、try-with-resources によってスローされた例外は抑制されます。言い換えれば、try-with-resources によってスローされる例外は抑制された例外であると言えます。

これらの例外は、Throwable クラスの getSuppress() メソッドを使用して取得できます。

例 :

上記の例では、次の場合にtry-with-resourcesステートメントから例外がスローされる可能性があります。

  • ファイルtest.txtが見つかりません。
  • BufferedReaderオブジェクトを閉じます。

tryブロックとtry -with-resourcesステートメントの両方から例外がスローされた場合、tryブロックからの例外はスローされ、try-with-resourcesステートメントからの例外は抑制されます。

抑制された例外の取得

Java 7 以降では、tryブロックによってスローされた例外からThrowable.getSuppressed()メソッドを呼び出すことで、抑制された例外を取得できます。

getSuppress() try-with-resources ステートメントによって抑制されたすべての例外を含む配列を返します。例外が抑制されていないか、抑制が無効になっている場合は、空の配列が返されます。

抑制された例外はcatchブロックで取得します。

catch(IOException e) {
  System.out.println("Thrown exception=>" + e.getMessage());
  Throwable[] suppressedExceptions = e.getSuppressed();
  for (int i=0; i<suppressedExceptions.length; i++) {
    System.out.println("Suppressed exception=>" + suppressedExceptions[i]);
  }
}

try-with-resources を使用する利点は次のとおりです。

  • コードが読みやすくなり、記述も簡単になります。
  • 自動リソース管理。
  • コードの行数が削減されます。
  • try-with-resources で複数のリソースが開かれると、依存関係の問題を回避するために、逆の順序でリソースが閉じられます。

Java 7 でこの機能が導入される前は、リソースのリークを避けるために、finallyブロックを使用してリソースが確実に閉じられるようにする必要がありました。

以下に、 Example 1に似たプログラムを示します。ただし、このプログラムでは、finally ブロックを使用してリソースを閉じています。

例 : Finally ブロックを使用してリソースを閉じる

import java.io.*;
class Main {
  public static void main(String[] args) {
    BufferedReader br = null;
    String line;
    try {
      System.out.println("Entering try block");
      br = new BufferedReader(new FileReader("test.txt"));
      while ((line = br.readLine()) != null) {
        System.out.println("Line =>"+line);
      }
    } catch (IOException e) {
      System.out.println("IOException in try block =>" + e.getMessage());
    } finally {
      System.out.println("Entering finally block");
      try {
        if (br != null) {
          br.close();
        }
      } catch (IOException e) {
        System.out.println("IOException in finally block =>"+e.getMessage());
      }
    }
  }
}

Entering try block
Line =>line from test.txt file
Entering finally block

finallyブロック内にもtry…catchブロックがあることに注目してください。これは、このFinallyブロック内でBufferedReaderインスタンスを閉じるときにIOException が発生する可能性があるため、この例外も捕捉されて処理されるためです。

try -with-resourcesステートメントは、自動リソース管理を行います。JVM がリソースを自動的に閉じるため、リソースを明示的に閉じる必要はありません。これにより、コードが読みやすく、記述しやすくなります。

複数のリソースを使用した try-with-resources

複数のリソースをセミコロンで区切ることで、try-with-resourcesブロック内で適切に宣言できます。

try (Scanner scanner = new Scanner(new File("testRead.txt"));
    PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) {
    while (scanner.hasNext()) {
	writer.print(scanner.nextLine());
    }
}

Java 9 より前では、try-with-resourcesブロック内でのみ新しい変数を使用できました。

try (Scanner scanner = new Scanner(new File("testRead.txt")); 
    PrintWriter writer = new PrintWriter(new File("testWrite.txt"))) { 
    // omitted
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy

final Scanner scanner = new Scanner(new File("testRead.txt"));
PrintWriter writer = new PrintWriter(new File("testWrite.txt"))
try (scanner;writer) { 
    // omitted
}"); background-repeat: no-repeat; background-position: center center; background-color: rgb(99, 177, 117);">Copy

上に示したように、スキャナー変数は明示的にFinal として宣言されているため、 try-with-resourcesブロックで使用できます。ライター変数は明示的に最終的なものではありませんが、最初の代入の後は変更されません。したがって、 writer変数も使用できます。

楽しく学習してください

Mouad Oumous Java WhatsApp グループに参加する

Mouad Oumous Telegram チャンネルに参加する

フォローして私たちの出版物をサポートしてください

Java での ModelMapper を使用したオブジェクト マッピングのガイド Spring Boot の開始: 初心者向けの包括的なチュートリアル Spring Boot Security | Spring Boot SSO | Okta を使用した OAuth2 Java8 ストリーム ベースの面接で最もよく聞かれる質問 - パート 2 コーディング: Javascript で配列をフラット化する Java8 ストリーム ベースの面接で最もよく聞かれる質問 - パート 1