-
이펙티브 자바 Item 9 - try-finally 대신 try-with-resources를 사용하라언어/Effective Java 2024. 5. 28. 12:04
자바 라이브러리에는 close 메서드를 호출해 직접 닫아줘야 하는 자원이 많다.
ex)InputStream, OutputStream, java.sql.Connection
자원 닫기는 클라이언트가 놓치기 쉬워서 예측할 수 없는 성능 문제로 이어지기도 한다.
전통적으로 자원이 제대로 닫힘을 보장하는 수단으로 try-finally가 쓰였다.
try-finally는 자원을 회수하는 최선의 방책이 아니다!
static void copy(String src, String dst) throws IOException { InputStream in = new FileInputStream(src); try { OutputStream out = new FileOutputStream(dst); try { byte[] buf = new byte[BUFFER_SIZE]; int n; while ((n = in.read(buf)) >= 0) out.write(buf, 0, n); } finally { out.close(); } } finally { in.close(); } }
- 자원이 많아지면 지저분해짐!! 가독성도 떨어진다.
try-with-resources
이 구조를 사용하려면, 해당 자원이 AutoCloseable인터페이스를 구현해야한다.
이 메서드는 단순히 close 메서드 하나만 정의한 인터페이스이다. 닫아야 하는 자원을 뜻하는 클래스를 작성한다면 해당 인터페이스를 구현해야 한다.
static void copy(String src, String dst) throws IOException { try (InputStream in = new FileInputStream(src); OutputStream out = new FileOutputStream(dst)) { byte[] buf = new byte[BUFFER_SIZE]; int n; while ((n = in.read(buf)) >= 0) out.write(buf, 0, n); } }
- 간결하게 선언 및 사용이 가능하다.
* AutoCLoseable 구현
public class MyResource implements AutoCloseable { public void doSomething() throws FirstError { System.out.println("doing something"); throw new FirstError(); } @Override public void close() throws SecondException { System.out.println("clean my resource"); throw new SecondError(); } }
public class MyResource implements AutoCloseable { public void doSomething() throws FirstError { System.out.println("doing something"); throw new FirstError(); } @Override public void close() throws SecondException { System.out.println("clean my resource"); throw new SecondError(); } } public class AppRunner { public static void main(String[] args) { MyResource myResource = new MyResource(); try { myResource.doSomething(); } finally { myResource.close(); } } }
- 이와 같이 작성하면, try블럭과 finally 블록에서 모두 예외가 발생할 수 있는데
- finally 예외가 try의 예외를 집어삼켜 버린다.
- 스택 추적에서 첫 번째 예외에 관한 정보가 남지 않게 되어, 실제 시스템에서 디버깅이 어렵다.
public class AppRunner { public static void main(String[] args) { try (MyResource myResource = new MyResource()){ myResource.doSomething(); } } }
- try-with-resources문을 사용하면, close의 예외가 숨겨지고 첫 번쨰 예외가 기록된다.
- 실전에서는 예외 하나만 보존되고 여러 개의 예외가 숨겨질 수 있다.
- 이렇게 숨겨진 예외들은 스택 추적 내역에 suppressed 꼬리표를 달고 출력된다.
- 자바7에서 Throwable에 추가된 getSuppressed 메서드를 쓰면 프로그램 코드에서 가져올 수 있수도 있다.!
참고자료
https://marxsoftware.blogspot.com/2012/04/java-7s-support-for-suppressed.html
'언어 > Effective Java' 카테고리의 다른 글
이펙티브 자바 Itme 10 - equals는 일반 규약을 지켜 재정의 하라 (0) 2024.05.28 이펙티브 자바 Item 11 - equals를 재정의하려거든 hashCode도 재정의하라 (0) 2024.05.28 이펙티브 자바 Item7 - 다 쓴 객체의 참조를 해제하라 (0) 2024.05.28 이펙티브 자바 Item6 - 불필요한 객체 생성을 피하라 (0) 2024.05.27 이펙티브 자바 Item5 - 자원을 직접 명시하지 말고 의존 객체 주입을 사용하라 (0) 2024.05.27