IT 개발 라이프/Back_End

자바(JAVA) try-with-resources

10Biliion 2024. 12. 31. 09:30

🧐 try-with-resources란?

Java 7에서 처음 도입된 try-with-resources는 리소스를 자동으로 닫아주는 구문입니다. 이전에는 finally 블록을 사용해 직접 리소스를 닫아야 했는데요, 이 기능 덕분에 코드는 간결해지고 오류 가능성도 줄어듭니다.

리소스는 java.lang.AutoCloseable 인터페이스를 구현해야만 사용할 수 있습니다.


✏️ 기본 사용법

try (ResourceType resource = new ResourceType()) {
    // 리소스를 사용하는 작업
} catch (Exception e) {
    // 예외 처리
}

📖 예제 코드

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

public class TryWithResourcesExample {
    public static void main(String[] args) {
        try (BufferedReader br = new BufferedReader(new FileReader("example.txt"))) {
            String line;
            while ((line = br.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

BufferedReaderFileReader를 사용해 파일을 읽는 예제입니다. 리소스는 작업이 끝나면 자동으로 닫힙니다.


🔍 AutoCloseable vs Closeable

리소스를 사용할 수 있는 조건은 두 가지 인터페이스 중 하나를 구현하는 것입니다.

  • AutoCloseable: Java 7에서 도입된 인터페이스로 모든 리소스가 구현할 수 있습니다.
  • Closeable: I/O 관련 클래스에서 주로 사용되며, AutoCloseable의 하위 인터페이스입니다.

AutoCloseableclose() 메서드는 Exception을 던질 수 있지만, Closeableclose() 메서드는 IOException만 던집니다.


🛠️ 여러 리소스 처리

try-with-resources는 여러 리소스를 세미콜론(;)으로 구분하여 처리할 수 있습니다.

📖 예제

try (
    BufferedReader br = new BufferedReader(new FileReader("example.txt"));
    FileWriter fw = new FileWriter("output.txt")
) {
    String line;
    while ((line = br.readLine()) != null) {
        fw.write(line + "\n");
    }
} catch (IOException e) {
    e.printStackTrace();
}

🤔 기존 방식과 비교

전통적인 try-finally 방식

BufferedReader br = null;
try {
    br = new BufferedReader(new FileReader("example.txt"));
    String line;
    while ((line = br.readLine()) != null) {
        System.out.println(line);
    }
} catch (IOException e) {
    e.printStackTrace();
} finally {
    if (br != null) {
        try {
            br.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

코드가 길고 복잡하죠? try-with-resources를 사용하면 이런 번거로움을 없앨 수 있습니다.


🔄 리소스 닫기 순서

리소스는 선언된 역순으로 닫힙니다.

📖 예제

try (
    ResourceA a = new ResourceA();
    ResourceB b = new ResourceB()
) {
    // 작업 수행
}

위 코드에서는 ResourceB가 먼저 닫히고, 그다음 ResourceA가 닫힙니다.


🧑‍💻 커스텀 리소스 만들기

사용자 정의 클래스도 AutoCloseable 인터페이스를 구현하면 사용할 수 있습니다.

📖 예제

class CustomResource implements AutoCloseable {
    @Override
    public void close() {
        System.out.println("리소스가 닫혔습니다.");
    }
}

public class CustomResourceExample {
    public static void main(String[] args) {
        try (CustomResource resource = new CustomResource()) {
            System.out.println("리소스를 사용 중입니다.");
        }
    }
}

출력 결과:

리소스를 사용 중입니다.
리소스가 닫혔습니다.

💡 예외 처리 개선

try-with-resources는 리소스를 닫는 과정에서 발생한 예외를 억제(suppression)하여 주요 예외에 포함시킵니다. 억제된 예외는 getSuppressed() 메서드로 확인할 수 있습니다.

📖 예제

public class SuppressedExceptionExample {
    public static void main(String[] args) throws Exception {
        try (ResourceA a = new ResourceA()) {
            throw new Exception("주요 예외");
        }
    }
}

class ResourceA implements AutoCloseable {
    @Override
    public void close() throws Exception {
        throw new Exception("닫기 예외");
    }
}

✨ try-with-resources의 장점

  1. 코드 간소화: finally 블록 없이 리소스를 닫을 수 있음.
  2. 안전성 향상: 리소스를 자동으로 닫아 누수 방지.
  3. 가독성 향상: 명확하고 간결한 코드 작성 가능.
  4. 예외 억제 관리: 닫기 과정에서 발생한 예외를 체계적으로 처리.