#09 try-finally보다는 try-with-resouces를 사용
Java 라이브러리에는 close 메서드를 호출해서 직접 닫아야 하는 InputStream, OutputStream 등이 있습니다.
try-finally 가 아닌, try-with-resource를 이용해서 닫는 방법에 대해 알아보겠습니다.
보통 finalizer를 통해 close 메서드를 호출하고 있지만, 이전에 언급했듯이 주의할 점들이 있습니다.
static String firstLineOfFile(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
br.close(); // 최선이 아님
}
}
만약 close 메서드를 하나 더 호출해야 하는 상황이라면, 지저분합니다.
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(); // 지저분함
}
}
Java 7에서 나온 try-with-resource를 이용하면 이러한 문제들을 해결할 수 있습니다.
이를 위해 AutoCloseable 인터페이스만 구현하면 됩니다.
AutoCloseable 인터페이스는 하나의 close 메서드만 정의되어 있습니다.
void close() throws Exception;
OutputStream을 보면, 아래와 같이 AutoCloseable 인터페이스가 이미 구현되어 있습니다.
이 외에도 많은 라이브러리들이 AutoCloseable 인터페이스를 구현하고 있습니다.
자세한 내용은 아래 링크를 참고해 주시기 바랍니다.
https://docs.oracle.com/javase/8/docs/api/java/lang/AutoCloseable.html
직접 구현해보면, 아래와 같이 구현할 수 있습니다.
static String firstLineOfFile(String path) throws IOException {
try(BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
// no finally and BufferedReader#close method.
}
static void copy(String src, String dst) throws IOException {
try(InputStream in = new FileInputStream(src)) {
try(OutputStream out = new FileOutputStream(dst)) {
byte[] buf = new byte[BUFFER_SIZE];
int n;
while ((n = in.read(buf)) >= 0) {
out.write(buf, 0, n);
}
}
// no finally and OutputStream#close method.
}
// no finally and InputStream#close method.
}
try-finally와 달리 try() 문 안에 AutoCloseable 인스턴스를 정의해야 합니다.
// try-finally
try {} finally {}
// try-with-resources
try(AutoCloseable instance) {}