-
Item 9. try-finally보다는 try-with-resource를 사용하라백수의 개발/이펙티브 자바 2019. 8. 9. 19:12
자바 라이브러리에는 InputStream, OutputStream, java.sql.Connection등 close메서드를 호출해 직접 닫아줘야 하는 자원이 많다.
이러한 자원을 닫기 위한 수단으로 try-finally가 사용되었다.
try-finally는 더 이상 자원을 회수하는 최선의 방책이 아니다!
아래와 같은 try-finally를 통해 자원을 닫을 수 있다.
static String firstLineOfFile(String path) throws IOException{ BufferedReader br = new BufferedReader(new FileReader(path)); try { return br.readLine(); } finally { br.close(); } }
그러나 자원을 하나 더 사용한다면 아래와 같이 코드가 작성될 것이다.
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 블록과 finally 블록 모두에서 발생할 수 있다.
쉽게 말해 firstLineOfFIle메서드에서 br.readLine()에서 예외가 발생할 수 하고, br.close()에서도 예외가 발생할 수 있다는 것이다.
만약, br.close()에서 예외가 다시 발생한다면, br.readLine()에서 예외가 발생했다는 정보는 없고, br.close()에서 발생한 오류 정보만 제공받게 된다.
AutoCloseable
이러한 문제는 자바7에서 새롭게 추가된 try-with-resource를 통해 해결 가능하게 되었다.
try-with-resource구조를 사용하기 위해서는 close메소드를 정의하기 위한 AutoCloseable 인터페이스를 구현해야한다.
try-with-resource
위의 try-finally로 구현한 코드를 try-with-resource로 구현하면 아래와 같다.
static String firstLineOfFile(String path) throws IOException{ try(BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } }
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); } } }
try-with-resource를 사용하게 되면 코드가 간결해지고, 가독성이 증가한다.
이는 try 블록에 있는 내용들이 실행완료되면, 알아서 AutoCloseable의 close메서드가 호출되어 자원을 닫게된다.
게다가 try-finally와 다르게 close에서 문제가 생기더라도 해당 예외가 숨겨진 채 try 블럭에서 발생 된 예외를 보여준다.
try-fianlly와 동일하게 try-with-resource에서도 catch절을 사용할 수 있어 try문을 중첩하지 않고도 다수의 예외를 처리할 수 있다.
static String firstLineOfFile(String path, String defaultVal) { try(BufferedReader br = new BufferedReader(new FileReader(path))) { return br.readLine(); } catch (IOException e){ return defaultVal; } }
마무리
꼭 회수해야 하는 자원을 다룰 때는 try-finally 대신 try-with-resource를 사용해라.
코드는 더 짧고 분명해지고, 만들어지는 예외 정보도 훨씬 유용하다.
try-with-resource는 정확하고 쉽게 자원을 회수할 수 있다.
'백수의 개발 > 이펙티브 자바' 카테고리의 다른 글
Item 11. equals를 재정의하려거든 hashCode도 재정의하라 (0) 2019.08.20 Item 10. equals는 일반 규약을 지켜 재정의하라 (0) 2019.08.13 Item 8. finalizer와 cleaner 사용을 피하라 (0) 2019.08.07 Item 7. 다 쓴 객체 참조를 해제하라 (0) 2019.07.19 Item 6. 불필요한 객체 생성을 피하라 (2) 2019.07.16