Try-with-resourcesのcatch
ブロックはオプションであると読みました。 Connection
オブジェクトをtry-with-resourcesブロック内に作成しようとしましたが、後続のcatch
ブロックはありません。Eclipseからコンパイラエラーを取得するためだけです: "Unhandled exception type SQLException
close()
の自動呼び出しによってスローされました。 "
Try-with-resourcesで使用できるすべてのリソースはAutoCloseable
を実装しているため、close()
メソッドの呼び出し時に例外がスローされる可能性があるため、catch
句はオプションであり、close()
からの例外のキャッチをスキップできないためです。
AutoCloseable
の特定の実装がclose()
メソッドでスローされた例外を直接宣言しないという特別な要件はありますか? (たとえば、例外をスローしないAutoCloseable
のclose() throws Exception
をclose()
でオーバーライドします)?
..またはこれはおそらくEclipseの問題ですか?
編集:これはまだ問題を引き起こしている最も簡単なコードの断片です:
try (Connection con = dataSource.getConnection()) {
/*...*/
}
これがJNDIデータソースの使用に関連するかどうかについての考え
前もって感謝します。
close()
がチェック済み例外をスローできない場合、これはオプションです。ただし、close()
が可能な場合、チェックされた例外は、catch
ブロックを使用するか、try-with-resources
ブロックが含まれているメソッドからスローすることによって、通常の方法で処理する必要があります。
詳細は JLS 14.2. にあります
14.20.3.2。リソースの拡張試行
少なくとも1つのcatch句またはfinally句を含むtry-with-resourcesステートメントは、拡張try-with-resourcesステートメントと呼ばれます。
拡張try-with-resourcesステートメントの意味:
try ResourceSpecification
Block
[Catches]
[Finally]
これは、try-catchまたはtry-finallyまたはtry-catch-finallyステートメント内にネストされた基本的なtry-with-resourcesステートメントへの次の変換によって与えられます。
try {
try ResourceSpecification
Block
}
[Catches]
[Finally]
変換の効果は、リソース指定をtryステートメントの「内側」に置くことです。これにより、拡張されたtry-with-resourcesステートメントのcatch句が、リソースの自動初期化またはクローズによる例外をキャッチできるようになります。
さらに、finallyキーワードの意図に沿って、finallyブロックが実行されるまでに、すべてのリソースが閉じられています(または閉じようとしています)。
これがJNDIデータソースの使用に関連しているかどうかについての考え
はい、そうです。
指定したtry-with-resoursesブロックの例では、SQLException
はaであるため、例外をキャッチして処理するか、ブロックが含まれるメソッドからスローする必要がありますチェック例外。
あなたはただ例外を投げている(または別のtry-catchブロックでそれをキャッチしている)可能性があります:
private static void test() throws IOException {
try(InputStream is = new FileInputStream("test.txt")) {
while(is.read() > -1) {
}
} finally {
// Will get executed, even if exception occurs
System.out.println("Finished");
}
}
すべてのJavaクラス(!)が例外をスローするわけではありません。自動クローズ機能を使用するために、try-with-resourcesを使用したいだけの場合もあります。
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
ReadLine()は(チェックされた)例外をスローしないため、このキャッチはオプションです。
はい、close()は例外をスローする可能性がありますが、try-with-resourcesもそれを処理します。
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
したがって、このリソースを試すことはキャッチを必要としません。
例外なしで、またはRuntimeExceptionを使用してAutoClosableのclose()メソッドを宣言することにより、明示的なcatchブロックを必要としないAutoClosableを作成できます。例外がなければ、catch-blockが不要であることは明らかです。さらに、コンパイラーはRuntimeExceptionがキャッチされるかどうかを静的にチェックしません(チェックされた例外とは対照的)。
例:
public class AutoClosableDemo
{
public static void main( final String[] args )
{
try (MyAutoCloseable1 mac1 = new MyAutoCloseable1())
{
System.out.println( "try-with-resource MyAutoCloseable1" );
}
try (MyAutoCloseable2 mac2 = new MyAutoCloseable2())
{
System.out.println( "try-with-resource MyAutoCloseable2" );
}
// The following is not allowed, because
// "Unhandled exception type Exception thrown by automatic close() invocation on mac3"
// try (MyAutoCloseable3 mac3 = new MyAutoCloseable3())
// {
// System.out.println( "try-with-resource MyAutoCloseable13" );
// }
System.out.println( "done" );
}
public static class MyAutoCloseable1 implements AutoCloseable
{
@Override
public void close()
{
System.out.println( "MyAutoCloseable1.close()" );
}
}
public static class MyAutoCloseable2 implements AutoCloseable
{
@Override
public void close() throws RuntimeException
{
System.out.println( "MyAutoCloseable2.close()" );
}
}
public static class MyAutoCloseable3 implements AutoCloseable
{
@Override
public void close() throws Exception
{
System.out.println( "MyAutoCloseable3.close()" );
}
}
}
JLSを確認することもできますが、これが言語が正しく動作する唯一の正しい方法である理由は比較的簡単です。
チェック例外の主なルールは、メソッドによって宣言されたチェック例外は、キャッチするか、呼び出し側のメソッドにスローさせることによって処理する必要があるということです。
Try-with-resourcesは常に(暗黙的に)closeメソッドを呼び出します。
したがって、使用するAutoClosableの特定のcloseメソッド(tryで宣言されたタイプによって決定される)がSQLExceptionなどのチェックされた例外をスローするように宣言している場合、このチェックされた例外をどこかで処理する必要があります。ルールに違反する可能性があります!
Closeメソッドがnotがチェック済み例外をスローすることを宣言する場合、ルールに違反しておらず、closeメソッドを暗黙的に呼び出すためにチェック済み例外を処理する必要はありません。スローされるように宣言されていないチェック済み例外をキャッチしようとすると、実際にはコンパイルの失敗です。