try-catch-finally
를 개선한 문법Closeable
인터페이스를 구현했고, 무조건 사용 후에 close()
메서드를 호출해야 한다close()
호출하지 않으면 바로 문제 발생 ⇒ 이를 해결하고자 나온 문법이 try-with-resources임AutoCloseable
인터페이스를 구현한 클래스에 대해서 자동으로 자원을 반납해주는 기능 제공Closeable
구현한 클래스들은 적용이 안되나…?AutoCloseable
인터페이스를 기존 Closeable
인터페이스의 부모 인터페이스로 추가했다는 점
만약 Closeable
의 자식으로 AutoCloseable
을 만들었다면, try-with-resouces를 적용하기 위해서는 기존의 Closeable
인터페이스를 구현한 모든 클래스들을 AutoCloseable
인터페이스를 구현하도록 수정해야 함
반대로 기존에 있던 Closeable
이 AutoCloseable
의 자식 인터페이스가 되어서 따로 수정할 필요가 없이 100% 호환 가능
try-catch-finally
말고 try-with-resources
를 사용해라public class Resource implements AutoCloseable {
@Override
public void close() throws RuntimeException{
System.out.println("close");
throw new IllegalStateException();
}
public void hello() {
System.out.println("hello");
throw new IllegalStateException();
}
}
public class ResourceTest {
public static void main(String[] args) {
ResourceTest srcTest = new ResourceTest();
srcTest.test1();
}
public void test1() {
Resource rsc = null;
try {
rsc = new Resource();
rsc.hello();
} finally {
if (rsc != null) {
rsc.close();
}
}
}
}
==결과==
Exception in thread "main" hello
java.lang.IllegalStateException
close
at org.delivery.api.example.Resource.close(Resource.java:8)
at org.delivery.api.example.ResourceTest.test(ResourceTest.java:17)
at org.delivery.api.example.ResourceTest.main(ResourceTest.java:6)
Resource.java:8
은 close()
메서드에서 발생한 예외다ResourceTest.java:17
도 finally
에서 rsc.close()
에서 발생한 예외다rsc.hello()
에서 발생한 IllegalStateException
에 대한 예외 trace는 누락됐다public void test2() {
try (Resource rsc = new Resource()) {
rsc.hello();
}
}
==결과==
> Task :api:ResourceTest.main() FAILED
hello
close
Exception in thread "main" java.lang.IllegalStateException
at org.delivery.api.example.Resource.hello(Resource.java:13)
at org.delivery.api.example.ResourceTest.test2(ResourceTest.java:25)
at org.delivery.api.example.ResourceTest.main(ResourceTest.java:7)
Suppressed: java.lang.IllegalStateException
at org.delivery.api.example.Resource.close(Resource.java:8)
at org.delivery.api.example.ResourceTest.test2(ResourceTest.java:24)
... 1 more
hello()
와 close()
모두에 대해서 stack trace가 남는다try-with-resources
써라public void test3() {
Resource rsc1 = null;
Resource rsc2 = null;
try {
rsc1.hello();
rsc2.hello();
} finally {
if (rsc1 != null) {
rsc1.close();
}
if (rsc1 != null) {
rsc1.close();
}
}
}
rsc1.close()
하는 경우에도 IllegalStateException
발생하지만, rsc2
도 반납될 거라고 생각함rsc2
는 정상적으로 반납되지 않는다.rsc1.close()
예외가 발생 → 이 부분을 또 try-catch-finally
로 묶어줘야 함public void test4() {
try (Resource rsc1 = new Resource(); Resource rsc2 = new Resource()) {
rsc1.hello();
rsc2.hello();
}
}
== 결과 ==
> Task :api:ResourceTest.main() FAILED
hello
close
close
rsc1
, rsc2
모두 close 된 것을 확인할 수 있다try-with-resources
에서 누락없이 모든 부분을 try-catch-finally
로 컴파일러가 변환을 해준다try-catch-finally
쓰지 말고, 컴파일러가 누락 없이 처리하도록 우리는 try-with-resources를 쓰자
⭐