본문 바로가기
Develop/Java

try-finally와 try-with-resource

by 준팍(junpak) 2023. 4. 5.
  • 자바 라이브러리에는 close메서드를 호출해 직접 닫아줘야하는 자원이 많다.
    • InputStream, OutputStream, Connection
  • 자원 닫기는 클라이언트가 놓치기 쉬워서 예측할 수 없는 성능 문제로 이어지기 도 한다.

finally 블럭

  • try-catch문과 함께 예외 발생 여부에 관계 없이 실행되어야할 코드를 포함시키기 위해 사용

      try {
          // 예외가 발생할 수 있는 코드
      } catch {
          // 예외 처리를 위한 코드
      } finally {
          // 예외 발생 여부와 관계없이 항상 실행되어야하는 코드
          // finally 블럭은 항상 try-catch문의 마지막에 위치한다.
      }
  • 순서

    • 예외 발생 시, try-catch-finally
    • 예외 미발생 시, try-finally
  • 자원 반납법

    • 하나만 반납할 때,

        public String firstLineOfFiles(String path) {
            BufferedReader bufferedReader = new BufferedReader(new Filereader(path))
            try {
                return bufferedReader.readLine();
            } catch (IOExection e){
                e.printStackTrace();
            } finally {
                try {  // close()는 예외를 발생시킬 수 있으므로 한 번더 감싸줘야한다.
                    if (bufferedReader != null) {
                        bufferedReader.close();
                    }
                } catch (IOExection e) {
                    e.printStackTrace();
                }
            }
        }
    • 둘 이상 반납할 때,

        public void copy(String src, String dst) {
            InputStream inputStream = new InputStream(src);
            try {
                OutputStream outputStream = new OutputStream(dst);
                try {
                    byte[] buffer = new byte[BUFFER_SIZE];
                    int n;
                    while ((n = in.read(buf)) >= 0) {
                        outputStream.write(buf, 0, n);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (outputStream != null) {
                            outputStream.close();
                        }
                    } catch (IOExection e) {
                        e.printStackTrace();
                    }
                } 
            } catch (IOExection e) {
                e.printStackTrace();
            } finally {
                try {
                    if (inputStream != null) {
                        inputStream.close();
                    }
                } catch () {
                    e.printStackTrace();
                }
            }
        }
    • 문제점

      • indent가 많이 늘어나 가독성이 떨어진다.
      • try 블럭과 finally 블럭 모두 예외 발생 시, try 블럭의 예외는 무시된다.
        (디버깅이 어려워진다.)

try-with-resource

  • JDK 1.7에서 추가

  • 조건 : 사용하려는 자원이 AutoClosable 인터페이스를 구현한다

      public interface Autocloseable {
          void close() throws Exception;
      }
  • 사용 시기 : 입출력(I/O) 관련 클래스 중 사용 후 반드시 close() 해야할 때

  • 사용 방법

    • try-with-resource 의 괄호 안에 자원 선언
    • try 블럭을 벗어나는 순간 자동으로 close() 호출
  • 사용 예시

    • 하나만 반납할 때,

        public String firstLineOfFiles(String path) {
            try (BufferedReader bufferedReader = new BufferedReader(
                        new Filereader(path))){
                return bufferedReader.readLine();
            } catch (IOExection e){
                e.printStackTrace();
            } 
        }
    • 둘 이상 반납할 때,

        public void copy(String src, String dst) {
            try (InputStream inputStream = new InputStream(src);
                        OutputStream outputStream = new OutputStream(dst)) {
                byte[] buffer = new byte[BUFFER_SIZE];
                int n;
                while ((n = in.read(buf)) >= 0) {
                    outputStream.write(buf, 0, n);
                }
            } catch (IOExection e) {
                e.printStackTrace();
            } 
        }
    • 장점

      • 간결하고 가독성이 좋다.
      • try 구문 내의 코드와 코드에 나타나지 않은 close() 호출 양쪽 모두 예외 발생 시,
        close()의 예외는 숨겨지고 try 구문 내의 예외만 기록된다.
      • close()에서 발생된 예외는 스택추적 내역에 (Suppressed)라는 머리말과 함께 출력된다.
    • 억제된 예외

      • 두 예외가 동시에 발생할 수 없기 때문에 실제 발생한 예외를 출력하고,
        close()로 인해 발생된 예외는 억제된 예외로 다룬다.

      • 억제된 예외에 대한 정보는 실제 발생된 예외 내부에 저장된다.

      • Throwable 내부의 억제된 예외 관련 메서드

          void addSuppressed(Throwable execption);  // 억제된 예외 추가
          Throwable[] getSuppressed()    // 억제된 예외(배열)을 반환

레퍼런스

'Develop > Java' 카테고리의 다른 글

표준 예외 vs 사용자 정의 예외  (0) 2023.04.05
추상 클래스와 인터페이스  (0) 2023.04.04
다형성  (0) 2023.04.04
제어자  (0) 2023.04.04
메서드 오버라이딩(Overriding)  (0) 2023.04.04