일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 공채
- github
- package-private
- 깃
- 컴퓨터과학
- Public
- 신입사원
- CS
- 메모리
- 깃허브
- 개발
- spring
- 자바
- 우리카드
- java
- OS
- 뮤텍스
- 스터디
- 신입
- 프로그래밍
- 스프링
- 운영체제
- Effective Java
- 이펙티브 자바
- 세마포어
- 정보처리기사
- 디지털
- 컴퓨터공학
- 알고리즘
- IT
- Today
- Total
주니어 개발자 성장기
아이템 9. try-finally 보다 try-with-resources를 사용하라. 본문
개요
- 자바 7부터 try-finally는 더 이상 최선의 방법이 아니다. (자바 7부터)
- try-with-resources를 사용하면 코드가 더 짧고 분명하다.
- 만들어지는 예외 정보도 더 유용하다.
try-finally의 문제점
// 코드 9-2 자원이 둘 이상이면 try-finally 방식은 너무 지저분하다! (47쪽)
static void copy(String src, String dst) throws IOException {
InputStream in = new FileInputStream(src);
try {
OutputStream out = new FileOutputStream(dst);
try {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
} finally {
out.close();
}
} finally {
in.close();
}
}
위와 같이 구현해야 안전하게 close 할 수 있다.
아래는 잘못 try-finally 구문의 잘못된 자원 회수 방법이다.
static void copy(String src, String dst) throws IOException {
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst);
try {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
} finally {
in.close();
out.close();
}
}
위 코드의 잘못된 점은 in.close();
에서 예외가 발생하면 out.close()
는 호출이 안되서 leak
이 발생한다는 것이다.
따라서, 자원이 여러개일 때, try-finally 구문의 중첩구조는 필연적이며 이는 코드의 가독성을 낮추고 작성하게 어렵기 만든다.
try-with-resources
try-with-resources를 사용하면 JVM이 컴파일 할 때 내부적으로 try-catch 구문을 이용해 안전한 자원회수가 가능하도록 해준다.
다음으로는 장점을 알아보자.
1. 훨씬 코드를 간결하게 만들어준다.
// 코드 9-4 복수의 자원을 처리하는 try-with-resources - 짧고 매혹적이다! (49쪽)
static void copy(String src, String dst) throws IOException {
try (InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dst)) {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0)
out.write(buf, 0, n);
}
}
위의 try-finally 구문과 비교하면 훨씬 간결하다.
2. 예외를 잡아먹지 않는다.
만약, try 구문과 finally 구문 둘 다에서 예외가 발생할 경우 가장 나중에 발생한 예외만 보이게 된다.
예시 코드를 보자.
//BadBufferedReader.class
@Override
public String readLine() throws IOException {
throw new CharConversionException();
}
@Override
public void close() throws IOException {
throw new StreamCorruptedException();
}
//TopLine.class
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
br.close();
}
}
위와 같이 readLine
, close
메서드를 오버라이드 하여 예외를 던지도록 하였다.(단지, 예시를 위해서) 이 경우 readLine
에서 먼저 예외가 발생하고 finally 구문으로 넘어가지만 close
에서도 예외가 발생하기 때문에, 가장 나중에 발생한 예외인 StreamCorruptedException
만 보이게 된다. 문제는 일반적으로 디버깅할 때 가장 처음 발생한 예외에 관심이 있다는 것이다.
하지만, try-with-resources로 다음과 같이 바꿔보자
static String firstLineOfFile(String path) throws IOException {
try(BufferedReader br = new BadBufferedReader(new FileReader(path))) {
return br.readLine();
}
}
앞서 말했듯 간결함이라는 장점과 더불어, 후속 예외까지 전부 보이게 된다.
결과
결론
- 반드시 자원을 정리할 때 try-finally 대신 try-with-resources를 사용하자.
- 간결함과 후속 예외를 쉽게 확인할 수 있다는 이점을 얻는다.
'Java > 이펙티브 자바' 카테고리의 다른 글
아이템 11. equals를 재정의하려거든 hashCode도 재정의하라. (0) | 2023.09.01 |
---|---|
아이템 10. equals는 일반 규약을 지켜 재정의하라 (0) | 2023.07.28 |
아이템 8. finalizer와 cleaner 사용을 피하라 (0) | 2023.07.22 |
아이템 7. 다 쓴 객체 참조를 해제하라. (0) | 2023.07.20 |
아이템 6. 불필요한 객체 생성을 피하라 (0) | 2023.07.17 |