web-dev-qa-db-ja.com

Javaのtry-with-resourcesはエラーまたは単なる例外をキャッチしますか?

また、閉じる必要のあるリソースを作成するjunitテストがあります。

このロジックを実装する1つの方法は、@Beforeおよび@Afterアプローチを使用することです。

私がしたことは、再利用するために作成をいくつかのユーティリティクラスにカプセル化することでした。例えば:

class UserCreatorTestUtil implements AutoClosable {
  User create() {...}
  void close() {...}
}

全体のポイントは、@Afterでオブジェクトを閉じることを忘れずに、オブジェクトがそれ自体を閉じることです。

使用法は次のとおりです。

@Test
void test() {
  try (UserCreatorTestUtil userCreatorTestUtil = new UserCreatorTestUtil()) {
    User user = userCreatorTestUtil.create();
    // Do some stuff regarding the user's phone
    Assert.assertEquals("123456789", user.getPhone());
  }
}

問題は、junitのassertキーワードがErrorではなくExceptionをスローすることです。

try-with-resourceはErrorを「キャッチ」し、closeメソッドを呼び出しますか?

* try-with-resources documentation で答えが見つかりませんでした。

53

catchなにもしません。しかし、finallyはすべてのリソースを閉じます。

finallyブロック エラーがスローされた場合でも実行されます

75
Thilo

基本的なtry-with-resourcesステートメントの擬似コードは(cf Java Language Specification §14.20.3.1 ):

final VariableModifiers_minus_final R Identifier = Expression;
Throwable #primaryExc = null;

try ResourceSpecification_tail
    Block
catch (Throwable #t) {
    #primaryExc = #t;
    throw #t;
} finally {
    if (Identifier != null) {
        if (#primaryExc != null) {
            try {
                Identifier.close();
            } catch (Throwable #suppressedExc) {
                #primaryExc.addSuppressed(#suppressedExc);
            }
        } else {
            Identifier.close();
        }
    }
}

ご覧のとおり、ThrowableではなくExceptionをキャッチしますが、これにはErrorが含まれますが、でのみプライマリ例外を取得しますリソースを閉じるときに発生した例外を抑制された例外として追加するため。

また、リソースがfinallyブロックで閉じられていることにも気付くことができます。つまり、彼らは何が起きても閉じられますSystem.exitもちろん、ErrorまたはThrowableのサブクラスがスローされた場合でも、現在実行中のJava Virtual Machine)を終了します。

37
Nicolas Filotto

Try-with-Resourcesは、それ自体では何もキャッチしません。

ただし、catchブロックをtry-with-resourcesブロックの最後に追加して、好きなタイプのThrowableをキャッチできます。

try (UserCreatorTestUtil userCreatorTestUtil = new UserCreatorTestUtil()) {
  // ... Whatever
} catch (RuntimeException e) {
  // Handle e.
} catch (Exception | Throwable t) {
  // Handle t.
}
13
Andy Turner

_try-with-resources_の背後にある考え方は、リソースが閉じられるようにすることです。

従来の_try-catch-finally_ステートメントの問題は、tryブロックが例外をスローすると仮定しましょう。通常、この例外はfinallyブロックで処理します。

ここで、finallyブロックでも例外が発生したとします。このような場合、try catchによってスローされる例外はlostであり、finallyブロックで生成された例外が伝播されます。

_try {
    // use something that's using resource
    // e.g., streams
} catch(IOException e) {
   // handle 
} finally {
    stream.close();
    //if any exception occurs in the above line, than that exception
    //will be propagated and the original exception that occurred
    //in try block is lost.
}
_

_try-with-resources_では、リソースのclose()メソッドが自動的に呼び出されます。close()が例外をスローした場合、残りのfinallyはそうではありません到達し、元の例外は失われます。

これと比較してください:

_try (InputStream inputStream= new FileInputStream("C://test.txt")){
    // ... use stream
} catch(IOException e) {
   // handle exception
}
_

上記のコードスニペットでは、close()メソッドが自動的に呼び出され、そのclose()メソッドも例外を生成した場合、その例外は自動的に抑制されます。

参照: Java Language Specification 14.20.

9
Raman Sahasi

あなたの終わりの誤解:try-with-resourcesはnotdocatchを行います。

finalfinallyを行うため、「問題」の種類は関係ありません。

詳細については [〜#〜] jls [〜#〜] をご覧ください!

5
GhostCat