programing

Java의 try-with-resources가 오류 또는 예외를 포착합니까?

copysource 2021. 1. 17. 11:49
반응형

Java의 try-with-resources가 오류 또는 예외를 포착합니까?


닫아야 할 리소스를 만드는 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을의 어설 션 키워드가 발생한다는 것입니다 Error하지 - Exception.

try-with-resource가 "catch" Error하고 close 메소드를 호출합니까?

* try-with-resources 문서 에서 답을 찾을 수 없습니다 .


catch아무것도 하지 않습니다 . 그러나 finally모든 리소스를 닫습니다.

finally블록 은 오류가 발생하더라도 실행됩니다 .


기본 try-with-resources 문의 의사 코드는 다음 Java Language Specification §14.20.3.1 같습니다 (cf ).

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는 그 자체로 아무것도 포착하지 못합니다.

그러나 catchtry-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블록 에서 처리합니다 .

Now suppose an exception occurs in finally block as well. In such a case, the exception thrown by try catch is lost and the exception generated in finally block gets propagated.

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.
}

In try-with-resources the close() method of the resource will get automatically called, and if the close() throws any exception, the rest of the finally isn't reached, and the original exception is lost.

Contrast that with this:

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

in the above code snippet, the close() method automatically gets called and if that close() method also generated any exception, than that exception will automatically get suppressed.

See also: Java Language Specification 14.20.3


Misconception on your end: try-with-resources does not do a catch.

It does a final finally, therefore the kind of "problem" doesn't matter.

See the JLS for further information!

ReferenceURL : https://stackoverflow.com/questions/40379293/does-javas-try-with-resources-catch-errors-or-just-exceptions

반응형