HomeAboutMeBlogGuest
© 2025 Sejin Cha. All rights reserved.
Built with Next.js, deployed on Vercel
🛁
공부기록
/
📚
책 정리
/
♟️
item9 - try-finally 보다는 try-with-resources를 사용하라
♟️

item9 - try-finally 보다는 try-with-resources를 사용하라

try-finally 보다는 try-with-resources를 사용하라


InputStream, OutputStream, java.sql.Connection 등은 close 메소드를 호출해 닫아줘야 한다. 하지만 이걸 클라이언트가 놓치면 성능 문제가 생긴다. 안전망으로 finalizer가 있지만 그리 믿을만 하지 못하다.(아이템8)
  • 위 방법대로 close를 호출하게 되면 문제가 발생할 수 있다. BufferdReader는 사용중 IOException이 발생할 수 있는데, 만약 br.readLine() 메소드에서 IOException이 발생하게 되면 메소드가 종료되므로 close가 호출되지 않고 스트림이 메모리에 남게된다.

전통적인 try-finally를 이용한 close해결

finally블록은 try, catch 블록이 끝난 뒤 실행할 로직을 정의해주는 블록이다. 따라서 이제 IOException이 발생하게 되더라도 상위 메소드로 IOException 객체를 던져준 뒤 finally 메소드를 종료하게 된다.
하지만 try-finally 방식은 자원을 둘 이상 사용하게 되면 코드가 지저분해지고 실수를 저지를 가능성이 커지게 된다.

try-finally의 문제점

  • 코드가 지저분해 지는 문제도 있지만 더 큰 문제가 존재한다.
  • inputString 메소드의 try 블록을 실행하던 도중 기기에 문제가 생긴다면 readLine이 정상적으로 실행되지 못하고 예외를 던지게 되고, 같은 이유로 finally 블록의 close 메소드도 예외를 던지게 된다.
  • 만약 이 예외들을 catch해서 상위 메소드에서 예외 정보를 체크해본다면, finally 블록에서 터딘 예외가 try 블록에서 생긴 예외를 집어 삼켜서 finally 블록의 예외만 체크하게 된다.
  • try 블록에서 터진 예외로 인해 finally 블록에서 예외가 발생했음에도 불구하고 최초 원인인 예외를 체크하지 못하게 되는 것이다.
  • 물론 적절한 코드를 통해 최초 원인을 체크할 수는 있지만 코드가 너무 지저분해지기 때문에 추천하는 방법은 아니다.

해결책

  • 위의 문제를 해결하기 위해 자바 7버전 부터는 try-with-resources 가 도입 되었다.
  • try-with-resources를 사용하기 위해서는 사용하는 자원이 AutoCloseable 인터페이스를 구현해야 한다.
  • 가독성이 좋아지고 예외가 발생했을 때 디버깅 하기에도 더 편리해졌다. inputString 메소드의 readLine과 close 모두에서 예외가 발생하는 경우 close호출 시 발생하는 예외는 숨겨지고 readLine 예외가 기록된다.
  • 이렇게 숨겨진 예외는 무시되는 것이 아니라 suppressed 상태가 되어 stackTrace 시 숨겨졌다는 메시지로 출력된다.
  • suppressed 상태가 된 예외는 자바7 부터 도입된 getSuppressed 메소드를 통해 가져와서 사용할 수 있다.
속성
2장
public static String inputString() throws IOException { BufferdReader br = new BufferdReader(new InputStreamReader(System.in)); String result = br.readLine(); br.close(); return result; }
public static String inputString() throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); try { return br.readLine(); } finally { br.close(); } }
public static void inputAndWriteString() throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); try { BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out)); try { String line = br.readLine(); bw.write(line); } finally { bw.close(); } } finally { br.close(); } }
public static String inputString() throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); try { return br.readLine(); } finally { br.close(); } }
public static String inputString() throws IOException { try (BufferedReader br = new BufferedReader(new InputStream(System.in))) { return br.readLine(); } }