Java/이펙티브 자바
아이템9. try-finally 보다 try-with-resources 를 사용하라.
PHM
2023. 6. 7. 10:17
핵심정리
- try-finally 는 더이상 최선의 방법이 아니다. (자바7부터)
- try-with-resources를 사용하면 코드가 더 짧고 분명하다.
- 만들어지는 예외 정보도 훨씬 유용하다.
static String firstLineOfFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
문제 1. 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();
}
}
- out.close가 실행이 안될 수 도 있다.
문제 2. try-finally
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();
}
}
- 코드에는 문제가 없지만, 코드가 너무 지저분하다.
문제 3. try-finally
public class TopLine {
// 코드 9-1 try-finally - 더 이상 자원을 회수하는 최선의 방책이 아니다! (47쪽)
static String firstLineOfFile(String path) throws IOException {
BadBufferedReader br = new BadBufferedReader(new FileReader(path));
try {
return br.readLine(); // CharConversionException
} finally {
br.close(); // StreamCorruptedException
}
}
public static void main(String[] args) throws IOException {
System.out.println(firstLineOfFile("pom.xml")); // 가장 나중에 발생한 예외인 StreamCorruptedException 가 보인다.
}
}
- 가장 처음의 발생한 예외를 알 수 없다.
- try-with-resources 를 사용한다면 두 가지 예외 순서대로 다 보인다.
해결 방안1. try-with-resources
// 코드 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);
}
}
}
- catch 문이나 finally 문도 사용 가능하다.
완벽공략
- p48, 자바 퍼즐러 예외 처리 코드의 실수
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 {
try {
out.close();
} catch (IOException e) { // IOException 이 아니라 런타임ex이 터진다면 catch 문 X
// TODO 안전한가?
}
try {
in.close();
} catch (IOException e) {
// TODO 안전한가?
}
}
}
- p49, try-with-resources 바이트코드
ㆍ중첩된 try-catch 문을 사용
ㆍaddSuppressed 함수로 에러를 순서대로 담아줘서 출력 ( 첫번째 에러 보존 )
ㆍclose 함수를 여러번 호출 - idempotent