자바/기본

try-with-resources

backend dev 2024. 3. 19.

try-with-resoucre를 안썼을경우

 

사용 후에 반납해주어야 하는 자원들은 Closable 인터페이스를 구현하고 있으며, 

사용 후에 close 메소드를 호출해주어야 했다.
Java7 이전에는 close를 호출하기 위해서 try-catch-finally를 이용해서 Null 검사와 함께 직접 호출해야 했는데, 

대표적으로 파일의 내용을 읽는 경우를 다음과 같이 구현할 수 있다.

public static void main(String[] args) throws IOException {
        String filePath = "C:\\KOSATEMP\\a.txt";

        FileInputStream fis = null;
        BufferedInputStream bis = null;

        try {
            fis = new FileInputStream(filePath);
            bis = new BufferedInputStream(fis);
            int data = -1;

            while ((data = bis.read()) != -1) {
                System.out.print((char) data);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            if (bis != null) {
                bis.close();
            }
            if (fis != null) {
                fis.close();
            }
        }

    }

 

close() 또한 IOException을 처리해야하므로 메소드에서 throws로 예외를 던지거나

finally에서 또다른 try-catch의 예외처리를 해야했다. 위에서는 throws를 한것이고

그게 아니였다면

finally {
    if (bis != null) {
        try {
            bis.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    if (fis != null) {
        try {
            fis.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

다음과 같이 됬을것이다. ( 상당히 코드가 지저분해진다.)

 

 

문제는 이러한 과정이 여러가지 단점을 가지고 있다는 것이다.

- 자원 반납에 의해 코드가 복잡해짐
- 작업이 번거로움
- 실수로 자원을 반납하지 못하는 경우 발생
- 에러로 자원을 반납하지 못하는 경우 발생
- 에러 스택 트레이스가 누락되어 디버깅이 어려움

 

그래서 이러한 문제를 해결하기 위해 try-with-resources라는 문법이 Java7부터 추가되었다.

Java는 이러한 문제점을 해결하고자 Java7부터 자원을 자동으로 반납해주는 try-with-resources 문법을 추가하였다.
Java는 AutoCloseable 인터페이스를 구현하고 있는 자원에 대해 try-with-resources를 적용 가능하도록 하였고
이를 사용함으로써 코드가 유연해지고, 누락되는 에러없이 모든 에러를 잡을 수 있게 되었다.

public static void main(String[] args) {
        String filePath = "C:\\KOSATEMP\\a.txt";
        
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));){
            int data = -1;

            while ((data = bis.read()) != -1) {
                System.out.print((char) data);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

try-with-resoucres를 적용해서 깔끔해진 코드

 

Closeable , AutoCloseable의 관계

사용후 반납해야하는 자원들은 Closeable인터페이스를 구현하고 있으며, Closeable 인터페이스는 AutoCloseable을 구현한다.

AutoCloseable이 늦게나온것인데 상식적으로 먼저 만들어진 인터페이스를 자식 클래스나 인터페이스에 사용하는 것이

일반적일 것이다. 하지만 Java 개발자들은 먼저 만들어진 Cloesable 인터페이스에 부모 인터페이스인 AutoCloesable을

추가함으로써 하위 호환성을 100% 달성함과 동시에 변경 작업에 대한 수고를 덜었다.

만약 Cloesable을 부모로 만들었다면 기존에 만들어준 클래스들이 모두 Cloesable이 아닌 AutoCloesable를

구현(implements) 하도록 수정이 필요했을 것이다.
하지만 이러한 구조 덕분에 기존에 구현된 자원 클래스들 모두 try-with-resources가 사용가능해졌다.

댓글