Пытается ли Java с ресурсами поймать ошибки или просто исключения?
у меня есть некоторые тесты junit, которые создают некоторые ресурсы, которые также должны быть закрыты.
одним из способов реализации этой логики является использование @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
.
будет ли попытка с ресурсом "поймать"Error
и вызвать метод close?
* не смог найти ответ в try-with-resources documentation.
5 ответов:
Это не
catch
ничего. Но это такfinally
закрыть все ресурсы.
finally
блоки запускаются даже при возникновении ошибки.
псевдокод базового try-with-resources оператор is (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
конечно, поскольку он завершает текущую виртуальную машину Java) даже в случаеError
или любой подклассThrowable
бросается.
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. }
идея
try-with-resources
, чтобы убедиться, что ресурсы должны быть закрыты.проблема с традиционными
try-catch-finally
заявления, что давайте предположим, что вашtry
блок выдает исключение; теперь обычно вы будете обрабатывать это исключение вfinally
блок.теперь предположим, что исключение происходит и в блоке finally. В таком случае исключение, вызванное try catch,проиграл и исключение, созданное в
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
theclose()
метод ресурса будет вызываться автоматически, и еслиclose()
выдает любое исключение, остальныеfinally
не достигается, и исходное исключение теряется.сравните это с этого:
try (InputStream inputStream= new FileInputStream("C://test.txt")){ // ... use stream } catch(IOException e) { // handle exception }
в приведенном выше фрагменте кода
close()
метод автоматически вызывается, и если этоclose()
метод также генерируется исключение, чем исключение автоматически подавленный.Читайте также: Спецификация Языка Java 14.20.3
заблуждение на вашем конце: try-with-resources делает не сделать лови.
Это финалнаконец-то, поэтому такой "проблемы" не имеет значения.
посмотреть JLS для получения дополнительной информации!