60

Java 7 には、 try-with-resources と呼ばれる新機能があります。それは何ですか?なぜ、どこでそれを使用する必要があり、どこでこの機能を利用できるのでしょうか?

このtryステートメントには、catch私を混乱させるブロックがありません。

4

7 に答える 7

89

これは、Java で使用される一部のリソース (SQL 接続やストリームなど) を適切に処理するのが難しいために導入されました。例として、Java 6 でInputStreamを適切に処理するには、次のようにする必要がありました。

InputStream stream = new MyInputStream(...);
try {
    // ... use stream
} catch(IOException e) {
   // handle exception
} finally {
    try {
        if(stream != null) {
            stream.close();
        }
    } catch(IOException e) {
        // handle yet another possible exception
    }
}

醜い二重の試みに気づきましたか?try-with-resources を使用すると、次のことができます。

try (InputStream stream = new MyInputStream(...)){
    // ... use stream
} catch(IOException e) {
   // handle exception
}

close()は自動的に呼び出され、IOException がスローされた場合は抑制されます ( Java 言語仕様 14.20.3で指定されているように) 。java.sql.Connection でも同じことが起こります

于 2013-07-19T06:30:37.273 に答える
18

ドキュメントに記載されているように:

try-with-resources ステートメントは、1 つ以上のリソースを宣言する try ステートメントです。リソースは、プログラムが終了した後に閉じる必要があるオブジェクトです。try-with-resources ステートメントは、各リソースがステートメントの最後で確実に閉じられるようにします。を実装するjava.lang.AutoCloseableすべてのオブジェクトを含む、 を実装するすべてのオブジェクトをjava.io.Closeableリソースとして使用できます。

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

static String readFirstLineFromFile(String path) throws IOException {
    try (BufferedReader br =
                   new BufferedReader(new FileReader(path))) {
        return br.readLine();
    }
}

この例では、try-with-resources ステートメントで宣言されたリソースは BufferedReader です。宣言ステートメントは、try キーワードの直後の括弧内に表示されます。Java SE 7 以降のクラス BufferedReader は、インターフェース java.lang.AutoCloseable を実装します。BufferedReader インスタンスは try-with-resource ステートメントで宣言されているため、try ステートメントが正常に完了したか突然完了したかに関係なく、インスタンスは閉じられます。

詳細はこちらからご覧いただけます。

于 2013-07-19T06:27:22.743 に答える
11

Java 9 リリース後の 2017 年からの更新

これで、Java 9より多くのシンタックス シュガーができ、リソースをブロックの外側で宣言することができますtry-catchが、それでも適切に処理されます。

Java 6たとえば、リソースを処理するこの方法を見てみましょう。

InputStream stream = new MyInputStream(...);
try {
    // ... use stream
} catch(IOException e) {
   // handle exception
} finally {
    try {
        if(stream != null) {
            stream.close();
        }
    } catch(IOException e) {
        // handle yet another possible exception
    }
}

ここで、他の回答で指摘されているように、このコードが非常に醜いことがわかります。

したがって、解決策はJava 7これを導入することでしたtry-catch-with-resource

try (InputStream stream = new MyInputStream(...)){
    // ... use stream
} catch(IOException e) {
   // handle exception
}

この表記法は確かに前のものよりもはるかに優れていますが、問題があります。リソース (この場合はストリーム) が以前に宣言されているが、このブロックで正しく処理されていることを確認したい場合は、次のようなトリックが必要です。

InputStream stream = new MyInputStream(...)
try (InputStream stream2 = stream) {
   // do something with stream being sure that is going to be closed at the end
} catch(IOException e) {
   // handle exception
}

この状況は、別の醜いコードでしか対処できないことがわかります。そのため、Java 9 では Try-With-Resources が改善され、新しい構文が導入されました。

InputStream stream = new MyInputStream(...)
try (stream) {
   // do something with stream being sure that is going to be closed at the end
} catch(IOException e) {
   // handle exception
}

この構文は、Java バージョン 8 またはマイナーのコンパイル時エラーになることに注意してください。

ほとんどのユースケースでは、try ブロックの範囲外のリソースは必要ありませんが、これはより「自然な」書き方です。 唯一の制限は、リーダー変数が事実上 final または単に final でなければならないことです。

于 2017-08-30T14:51:51.760 に答える
6

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

  • nullリソースを閉じる前に、リソースが存在するかどうかを確認する必要があります
  • クロージング自体が例外をスローする可能性があるため、finally別のものを含める必要がありましたtry-catch
  • プログラマーはリソースを閉じるのを忘れがちです

最初の 2 つは主に構文の問題ですが、最後の 1 つはより重大です。したがって、try-with ステートメントを使用すると、コードがよりクリーンになり、最も重要なことは、リソースが常に閉じられることです:-)

于 2013-07-19T06:31:25.703 に答える