[아이템 9] try-finally 보다는 try-with-resources를 사용하라
-
자바 라이브러리에는 close 메서드를 호출해 직접 닫아줘야 하는 자원이 많음(InputStream, OutputStream, java.sql.Collection 등)
-
finalizer를 사용해도 되지만 아이템 8에서 봤듯이 믿을만한 요소가 아님
-
전통적으로는 try-finally를 사용함
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
br.close();
}
}
- 여기서 위의 try-finally에서 자우너을 하나 더 사용하면 아래와 같이 됨(하나 쓴 걸로 지저분해짐)
static String firstLineOfFile(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();
}
}
-
만약 물리적인 문제가 생겨서 firstLineOfFile 메서드 안의 readLine 메서드가 예외를 던지고 같은 이유로 close 메서드도 실패할 것임, 이런 상황에서 두 번째 예외가 첫 번째 예외를 완전히 집어삼킴, 이러면 실제 시스템에서의 디버깅도 몹시 어려움, 아무리 첫 번째 예외에 기록하도록 처리해도 코드가 길어짐
-
이때 try-with-resources를 통해서 해결할 수 있음, 이 구조를 사용하기 위해서 해당 자원은 AutoCloseable 인터페이스를 구현해야함, 단순히 void를 반환하는 close 메서드하나만 정의한 인터페이스임
-
자바 라이브러리와 서드파티 라이브러리들의 수많은 클래스와 인터페이스가 이미 AutoCloseable을 구현하거나 확장함, 닫아야 하는 자원을 뜻하는 클래스를 작성하려면 AutoCloseable을 반드시 구현해야함
-
try-with-resource로 고쳐쓰면 아래와 같이 쓸 수 있음
static String firstLineOfFile(String path) throws IOException {
try(BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
static void copy(String src, String dst) throws IOException {
try (InputStream in = new InputStream(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);
}
}
-
위와 같이 처리한다면 문제를 진단하기 수월해짐, 만약 readLine과 close에 예외가 발생하면 close에서 발생한 예외는 숨겨지고, readLine에서 발생한 예외는 기록됨
-
이렇게 보여줄 예외 하나만 보존되고 여러 개의 다른 예외가 숨겨질 수 있음, 이렇게 숨겨진 예외들도 그냥 버려지지 않고 스택 추적 내역에 숨겨졌다는 꼬리표를 달고 출력됨, Throwable에 추가된 getSuppressed 메서드를 이용해서 코드를 가져올 수 있음
-
여기서 catch를 추가해서 쓸 수 있음, try문을 중첩하지 않고도 다수의 예외를 처리 가능함
static String firstLineOfFile(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
} catch (IOException e) {
return defaultVal;
}
}
-
꼭 회수해야 하는 자원을 다룰 때는 try-finally 말고 try-with-resources를 사용하자, 예외는 없음, 코드는 더 짧고 분명해지고, 만들어지는 예외 정보도 훨씬 유용함
-
try-finally로 작성하면 실용적이지 못할 만큼 코드가 지저분해지는 경우라도, try-with-resources로는 정확하고 쉽게 자원을 회수할 수 있음
Author And Source
이 문제에 관하여([아이템 9] try-finally 보다는 try-with-resources를 사용하라), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@gang_shik/아이템-9-try-finally-보다는-try-with-resources를-사용하라저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)