Java 7 には、 try-with-resources と呼ばれる新機能があります。それは何ですか?なぜ、どこでそれを使用する必要があり、どこでこの機能を利用できるのでしょうか?
このtry
ステートメントには、catch
私を混乱させるブロックがありません。
Java 7 には、 try-with-resources と呼ばれる新機能があります。それは何ですか?なぜ、どこでそれを使用する必要があり、どこでこの機能を利用できるのでしょうか?
このtry
ステートメントには、catch
私を混乱させるブロックがありません。
これは、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 でも同じことが起こります
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 ステートメントが正常に完了したか突然完了したかに関係なく、インスタンスは閉じられます。
詳細はこちらからご覧いただけます。
これで、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 でなければならないことです。
Java では、入力ストリームや出力ストリームなどのリソースを使用する場合、使用後に常に閉じる必要があります。また、例外をスローする可能性があるため、try
catch
ブロック内にある必要があります。クロージングはfinally
ブロック内にある必要があります。これは少なくとも Java 7 までの方法です。これにはいくつかの欠点があります。
null
リソースを閉じる前に、リソースが存在するかどうかを確認する必要がありますfinally
別のものを含める必要がありましたtry
-catch
最初の 2 つは主に構文の問題ですが、最後の 1 つはより重大です。したがって、try-with ステートメントを使用すると、コードがよりクリーンになり、最も重要なことは、リソースが常に閉じられることです:-)