[JAVA] try-with-resources와 AutoCloseable 인터페이스
자바 7에서 도입된 try-with-resources는 자원 관리를 훨씬 쉽고 안전하게 만들어주는 기능이다.
기존의 try-finally 구문을 대체하며, 코드의 가독성과 안정성을 크게 향상시킨다.
기존 방식의 문제점
전통적인 자원 관리 방식은 다음과 같은 문제가 있다:
FileInputStream fis = null;
try {
fis = new FileInputStream("file.txt");
// 파일 처리 로직
} catch (IOException e) {
// 예외 처리
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
// close() 메서드의 예외 처리
}
}
}
이 코드의 문제점:
- 중첩된 try-catch 블록으로 인한 복잡성
- close() 호출 시 발생하는 예외 처리 누락 가능성
- 여러 리소스 사용 시 코드가 더욱 복잡해짐
try-with-resources 사용법
같은 기능을 try-with-resources로 구현하면 훨씬 간단해진다:
try (FileInputStream fis = new FileInputStream("file.txt")) {
// 파일 처리 로직
} catch (IOException e) {
// 예외 처리
}
여러 리소스를 함께 사용할 때:
try (FileInputStream fis = new FileInputStream("input.txt");
FileOutputStream fos = new FileOutputStream("output.txt")) {
// 파일 처리 로직
} catch (IOException e) {
// 예외 처리
}
AutoCloseable 인터페이스 구현
커스텀 리소스 클래스를 try-with-resources와 함께 사용하려면 AutoCloseable 인터페이스를 구현해야 한다:
public class CustomResource implements AutoCloseable {
private boolean resourceInUse;
public CustomResource() {
this.resourceInUse = true;
System.out.println("리소스 할당");
}
public void doSomething() {
if (!resourceInUse) {
throw new IllegalStateException("리소스가 이미 해제됨");
}
System.out.println("리소스 사용 중");
}
@Override
public void close() {
if (resourceInUse) {
resourceInUse = false;
System.out.println("리소스 해제");
}
}
}
사용 예제:
try (CustomResource resource = new CustomResource()) {
resource.doSomething();
// 자동으로 close() 호출
}
실전 활용 예제
데이터베이스 연결 관리
public class DatabaseConnection implements AutoCloseable {
private Connection conn;
public DatabaseConnection(String url) throws SQLException {
this.conn = DriverManager.getConnection(url);
}
public void executeQuery(String sql) throws SQLException {
try (Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery(sql);
// 결과 처리
}
}
@Override
public void close() throws SQLException {
if (conn != null && !conn.isClosed()) {
conn.close();
}
}
}
파일 처리 유틸리티
public class FileProcessor implements AutoCloseable {
private BufferedReader reader;
private BufferedWriter writer;
public FileProcessor(String inputPath, String outputPath) throws IOException {
this.reader = new BufferedReader(new FileReader(inputPath));
this.writer = new BufferedWriter(new FileWriter(outputPath));
}
public void processLines() throws IOException {
String line;
while ((line = reader.readLine()) != null) {
writer.write(processLine(line));
writer.newLine();
}
}
private String processLine(String line) {
return line.toUpperCase();
}
@Override
public void close() throws IOException {
try (reader; writer) {
// Java 9부터 가능한 try-with-resources 향상된 문법
}
}
}
주의사항과 팁
- 예외 처리 우선순위
- try 블록에서 예외가 발생하고, close()에서도 예외가 발생하면 try 블록의 예외가 전파됨
- close()의 예외는 suppressed 예외로 추가됨
try (CustomResource resource = new CustomResource()) {
throw new RuntimeException("try 블록 예외");
} catch (Exception e) {
// try 블록의 예외가 잡힘
Throwable[] suppressed = e.getSuppressed();
// suppressed 예외 처리
}
- Null 리소스 처리
// null 리소스는 안전하게 무시됨 try (FileInputStream fis = shouldCreateStream() ? new FileInputStream("file.txt") : null) { if (fis != null) { // 파일 처리 } }
- 자원 해제 순서
- 선언된 순서의 역순으로 close() 호출
- 가장 마지막에 생성된 리소스부터 해제
실무 적용 시 장점
- 코드 간결성
- finally 블록 없이도 안전한 리소스 해제
- 중첩된 try-catch 블록 제거
- 안정성
- 실수로 리소스를 해제하지 않는 상황 방지
- 모든 예외가 적절히 처리됨
- 유지보수성
- 리소스 관리 로직이 분리되어 비즈니스 로직에 집중 가능
- 표준화된 방식으로 리소스 관리
'개발&프로그래밍' 카테고리의 다른 글
[JAVA] 가비지 컬렉션 동작 원리와 모니터링 방법 (1) | 2024.11.14 |
---|---|
[IntelliJ IDEA] 코드 리팩토링을 도와주는 플러그인 TOP 5 (0) | 2024.11.05 |
[JAVA] 직렬화(Serializable)와 역직렬화 (6) | 2024.11.03 |
[JAVA] equals()와 hashCode() 메서드 (0) | 2024.11.02 |
[JAVA] Stream의 map과 flatMap 차이 (0) | 2024.11.01 |
댓글