자바 7부터 try-with-resource 가 등장했다. try-with-resource를 사용하면 코드의 가독성이 훨씬 좋아진다는 장점이 있다.
아래의 예제를 통해 살펴보자.
[기존 try-catch-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();
}
}
[try-with-resource]
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-catch-finally 는 중첩된 코드로 가독성이 좋지 않았다.
하지만 단순히 가독성만을 위해 try-resource 코드가 생긴것은 아닐 것이다.
기존 코드가 추가로 좋지 않았던 점은 기존 try-catch-finally 코드는 Exception을 모두 보여주지 않는 것이었다.
아래 예제를 통해 살펴보자. BefferedReader 를 구현한 BadBufferedReader 클래스이다.
상속을 통해 구현된 readLine() 과 close() 에서 각각의 Exception 을 발생하고 이 클래스를
public class BadBufferedReader extends BufferedReader {
public BadBufferedReader(Reader in, int sz) {
super(in, sz);
}
public BadBufferedReader(Reader in) {
super(in);
}
@Override
public String readLine() throws IOException {
throw new CharConversionException();
}
@Override
public void close() throws IOException {
throw new StreamCorruptedException();
}
}
JDK7 에 등장한 try-with-resource 구문과 이전의 try-catch-finally 구문안에서 각각 실행하여 Exception 을 모두 발생시켜 볼 예정이다.
[try-with-resource]
static String tryResourceExample(String path) throws IOException {
try(BufferedReader br = new BadBufferedReader(new FileReader(path))) {
return br.readLine();
}
}
[try-catch-finally]
static String tryFinallyExample(String path) throws IOException {
BadBufferedReader br = new BadBufferedReader(new FileReader(path));
try{
return br.readLine();
}catch (Exception e) {
System.out.println(e.getCause());
}finally {
br.close();
}
return null;
}
[try-with-resource console]
[try-catch-finally console]
기존 try-catch-finally 에서는 처음 발생한 Exception이 보이지 않고 가장 밖에 있던 Exception만 로그에 찍히지만 try-with-resource 에서는 그대로 stack 에 쌓여 로그에 남겨진다.
어떻게 stack 에 두개의 두 exception 로그를 남길 수 있는지 try-with-resource (바이트 코드에서 디컴파일된 클래스 파일)로 확인할 수 있다.
try-with-resource로 구현된 코드를 바이트 코드에서는 위와 같이 구현해 준다.
finally 가 사라지고 중첩된 try-catch 문으로
throw 문 발생시 addSuppressed() 함수로 무시될 수 있는 예외를 포함 시키고 있다. 그래서 stack 에 같이 남을 수 있는 것이다.
addSuppressed() 함수는 무시되는 예외를 표시하기 위해 Java7 에서 포함된 함수이다.
이밖에 try-with-resource의 가독성에서의 장점이라 하면 try() 안에 여러개의 리소스를 넣어서 한번에 사용할 수 있다는 점이다.
try() 함수의 Required Type 이 AutoCloseable 인것도 추가로 알아두면 좋다.
try-with-resource 에서 AocoCloseable에 있는 close()를 직접 호출하여 finally안에서 close() 를 명시적으로 호출 할 필요가 없다.
public interface Closeable extends AutoCloseable {
/**
* Closes this stream and releases any system resources associated
* with it. If the stream is already closed then invoking this
* method has no effect.
*
* <p> As noted in {@link AutoCloseable#close()}, cases where the
* close may fail require careful attention. It is strongly advised
* to relinquish the underlying resources and to internally
* <em>mark</em> the {@code Closeable} as closed, prior to throwing
* the {@code IOException}.
*
* @throws IOException if an I/O error occurs
*/
public void close() throws IOException;
}
static void example(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);
}
}
'java' 카테고리의 다른 글
코어의 수 확인하기(Get OS-level system information) (0) | 2022.03.29 |
---|---|
[JAVA]옵저버 패턴 예제 (0) | 2022.01.27 |
[JAVA] 람다식 실용예제 - 실행 어라운드 패턴 (0) | 2021.12.24 |
디자인 패턴(Design Pattern) - 목적에 따른 분류 (0) | 2021.11.26 |
[JAVA]java Serializable (0) | 2021.11.04 |