반응형
아이템 9 - try-finally 보다 try-with-resouces 를 사용하라 - 완벽 공략
이 글은 백기선 님의 이펙티브 자바 강의와 이펙티브 자바 3 / E 편을 참고하여 작성하였습니다.
finally 블럭에서 try - catch 로 다시 감싸져있다면 어떻게 될까?
public class Copy {
private static final int BUFFER_SIZE = 8 * 1024;
// 코드 9-2 자원이 둘 이상이면 try-finally 방식은 너무 지저분하다! (47쪽)
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) {
// TODO 이렇게 하면 되는거 아닌가?
}
try {
in.close();
} catch (IOException e) {
// TODO 안전한가?
}
}
}
public static void main(String[] args) throws IOException {
String src = args[0];
String dst = args[1];
copy(src, dst);
}
}
겉으로 봤을 때는 안전해 보이지만 안전하지 않다.
위의 코드는 IOException
을 잡고있지만 IOException
이 아닌 다른 오류가 발생한다면
뒤의 코드는 실행되지 않는다.
public class Copy {
private static final int BUFFER_SIZE = 8 * 1024;
// 코드 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();
}
}
public static void main(String[] args) throws IOException {
String src = args[0];
String dst = args[1];
copy(src, dst);
}
}
finally 블럭에서 try - catch 로 다시 감싸는 것 보다는 위의 코드가 훨씬 안전하다.
try-with-resources 사용하면 훨씬 간결하게 문제를 해결할 수 있다.
try-with-resources 바이트코드
public class TopLine {
public TopLine() {
}
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
String var2;
try {
var2 = br.readLine();
} catch (Throwable var5) {
try {
br.close();
} catch (Throwable var4) {
var5.addSuppressed(var4);
}
throw var5;
}
br.close();
return var2;
}
public static void main(String[] args) throws IOException {
String path = args[0];
System.out.println(firstLineOfFile(path));
}
}
try-with-resources 코드가 컴파일러에서 빌드 된 뒤의 클래스 파일이다.
try {
var2 = br.readLine();
} catch (Throwable var5) {
try {
br.close();
} catch (Throwable var4) {
var5.addSuppressed(var4);
}
throw var5;
}
만약 코드 실행 중 예외가 발생했을 때 첫번째 예외를 throw 하지만
후속으로 발생한 예외가 있다면 addSuppressed 를 호출해 후속으로 발생한 에러를 담아준다.
컴파일러된 코드를 보면 close() 메서드가 여러번 호출되고 있다.
그래서 close() 를 구현할 때는 멱등성을 가져야 한다.
반응형
'개발 공부 > Java' 카테고리의 다른 글
이펙티브 자바 아이템 10 - equals 는 일반 규약을 지켜 재정의하라 - 완벽 공략 (0) | 2022.10.24 |
---|---|
이펙티브 자바 아이템 10 - equals 는 일반 규약을 지켜 재정의하라 - 핵심 정리 (0) | 2022.10.19 |
이펙티브 자바 아이템 9 - try-finally 보다 try-with-resouces 를사용하라 - 핵심 정리 (0) | 2022.10.14 |
이펙티브 자바 아이템 8 - finalizer 와 cleaner 사용을 피하라 - 완벽 공략 (0) | 2022.10.14 |
이펙티브 자바 아이템 8 - finalizer와 cleaner 사용을 피하라 - 핵심 정리 (0) | 2022.10.12 |
댓글