일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 서평단
- Oracle 사용자명 입력
- oracle 18c
- Orace 18c
- ora-01722
- Oracle 테이블 띄어쓰기
- 비전공자를 위한 데이터베이스 입문
- ORA-12899
- ORA-00922
- 무료 오라클 데이터베이스
- Oracle 테이블 대소문자
- 윈도우 Oracle
- Oracle 18c HR schema
- Oracle 18c 설치
- 오라클 캐릭터셋 변경
- Oracle Express Edition
- Oracle 윈도우 설치
- 오라클 캐릭터셋 확인
- Oracle 사용자명
- Oracle 초기 사용자
- oracle
- Oracle 18c HR
- 무료 오라클 설치
- 오라클 캐릭터셋 조회
- Today
- Total
The Nirsa Way
[Effective Java 3/E - 객체 생성과 파괴] Item 9. try-finally 보다는 try-with-resources를 사용하라 본문
[Effective Java 3/E - 객체 생성과 파괴] Item 9. try-finally 보다는 try-with-resources를 사용하라
KoreaNirsa 2025. 7. 13. 14:40
try-finally 보다는 try-with-resources를 사용하라
try-finally의 경우 인스턴스를 명시적으로 close()를 호출하여 닫아주어야 합니다. 만약 개발자의 실수로 자원을 제대로 닫지 않는다면 성능의 문제가 발생할 가능성이 있으며 try와 finally 모두 예외가 발생된다면 try에서 발생한 예외가 덮어씌워질 수 있습니다.
file.txt의 첫번째 줄을 읽은 후 출력하는 코드를 try-finally를 사용하여 구현한다고 하면 아래와 같이 될겁니다.
finally를 주의 깊게 본다면 reader가 null이 아닌지 체크(NPE 방지)를 하고 close()를 수행합니다. 하지만 close() 수행 중 IOException이 발생할 가능성이 있으므로 또 다시 try-catch를 사용하여 예외를 처리해주어야 합니다.
파일을 읽고 출력하는 아주 간단한 코드이지만 길고 복잡해지며 NPE 방지, close() 누락 등 개발자의 실수가 발생할 수 있으며, 예외 발생 시 디버깅이 어려워 집니다. try와 close() 양쪽의 예외에서 한쪽의 예외만 보일 수 있기 때문입니다. 이러한 문제들로 인해 try-with-resources 방식을 권장합니다.
public class Test {
public static void main(String[] args) throws InterruptedException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("file.txt"));
String line = reader.readLine();
System.out.println(line);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
위와 똑같은 기능을 구현하는 코드이지만 코드가 훨씬 더 간단해졌으며, 개발자의 실수를 유도할 코드가 사라졌습니다. (NPE 방지, close 등) try-with-resources는 자동으로 close()를 호출해주므로 개발자가 따로 작성할 필요가 없습니다.
public class Test {
public static void main(String[] args) throws InterruptedException {
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
String line = reader.readLine();
System.out.println(line);
} catch (IOException e) {
e.printStackTrace();
}
}
}
만약 여러 리소스를 사용해야 한다면 아래이 try에 여러 리소스를 생성하여 사용할 수 있습니다.
public class Test {
public static void main(String[] args) throws InterruptedException {
try (FileInputStream fis = new FileInputStream("input.txt");
FileOutputStream fos = new FileOutputStream("output.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
BufferedOutputStream bos = new BufferedOutputStream(fos)) {
int data;
while ((data = bis.read()) != -1) {
bos.write(data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
try-with-resources를 사용하기 위해서는 AutoCloseable을 상속받아라.
단, try-with-resources의 경우 AutoCloseable를 상속받아야만 사용이 가능합니다. AutoCloseable은 try-with-resources와 함께 사용할 수 있도록 설계되었으며 이름처럼 자동으로 close()를 호출되도록 보장해줍니다. 많은 Java의 클래스들이 AutoClosable 인터페이스를 구현하며 LIFO(후입선출) 방식으로 닫힙니다.
만약, AutoCloseable을 상속받지 않은 상태로 try-with-resources를 사용하려 한다면 "The resource type MyResource does not implement java.lang.AutoCloseable" 컴파일 에러가 발생합니다.
직접 만든 클래스에 AutoCloseable을 적용하려면 상속받은 후 close() 메서드를 오버라이딩 해주면 됩니다.
public class Test {
public static void main(String[] args) throws InterruptedException {
try (MyResource res = new MyResource()) {
res.doSomething();
} catch (Exception e) {
e.printStackTrace();
}
}
}
// AutoCloseable 상속
class MyResource implements AutoCloseable {
public void doSomething() {
System.out.println("리소스 사용 중...");
}
// close() 오버라이딩
@Override
public void close() {
System.out.println("리소스 정리 중(close 호출됨)");
}
}
만약, 강제로 예외를 발생시켜도 close는 정상적으로 호출되어 리소스가 닫힙니다.
public class Test {
public static void main(String[] args) throws InterruptedException {
try (MyResource res = new MyResource()) {
// 강제로 예외 발생시키기
throw new RuntimeException("강제 예외 발생");
} catch (Exception e) {
e.printStackTrace();
}
}
}
class MyResource implements AutoCloseable {
public void doSomething() {
System.out.println("리소스 사용 중...");
}
@Override
public void close() {
System.out.println("리소스 정리 중(close 호출됨)");
}
}
이와 같은 이유로 사용 후 꼭 회수(close)해야하는 자원을 다룰때는 try-with-resources를 사용하는것이 좋습니다.