ITEM 9 "try-with-resource 를 사용하라"
이 ITEM 을 확인하기 전에 위 백기선님의 Effective Java 해설 영상을 보는 것을 추천한다.
자바 라이브러리에는 InputStream, OutputStream, java.sql.Connection 과 같이 정리해야 되는 리소스들이 많다.
전통적으로 try-finally 를 사용해서 많이 예외처리를 해왔는데 아래와 같은 문제점들이 있어 Java 7 부터 제공하는 try-with-resource 구문을 사용하는 것을 권장하고 있다.
전통적인 try-finally 문제점
public class MyResource implements AutoCloseable {
public void doSomething() {
System.out.println("Do something");
throw new FirstError();
}
@Override
public void close() throws Exception {
System.out.println("Close my Resource");
throw new SecondError();
}
}
public class FirstError extends RuntimeException { }
public class SecondError extends RuntimeException { }
public class Main {
public static void main(String[] args) {
MyResource myResource = new MyResource();
try {
myResource.doSomething();
} finally {
myResource.close();
}
}
}
위 코드처럼 try-finally 를 사용할 경우, 첫 번째 에러는 알 수가 없다. doSomething 에서 첫 번째 에러가 발생한 후 finally 구문으로 넘어와 close 에서 두 번째 에러를 발생하는데 두 번째 에러가 첫 번째 에러를 삼켜 버린다. 보통 우리는 문제 해결을 위해 첫 번째 에러가 어디서 발생하였는지 알고 싶다.
public class Main {
public static void main(String[] args) {
MyResource myResource = new MyResource();
try {
myResource.doSomething();
MyResource myResource2 = null;
try {
myResource2 = new MyResource();
myResource2.doSomething();
} finally {
if (myResource2 != null) {
myResource2.close();
}
}
} finally {
myResource.close();
}
}
}
심지어 Resource 를 하나 더 생성해서 무언가를 수행하면 try-finally 구문이 nested 된 형식으로 계속해서 중첩되는 것을 볼 수 있다. 가독성도 떨어지고 실수할 가능성도 많아진다. 차라리 자바 7부터 제공하는 try-with-resource 를 사용하자.
public class Main {
public static void main(String[] args) {
try(MyResource myResource = new MyResource();
MyResource myResource2 = new MyResource()) {
myResource.doSomething();
myResource2.doSomething();
} catch (Throwable e) {
Throwable[] suppExe = e.getSuppressed();
System.out.println("Suppressed Exception Array" + " length = " + suppExe.length);
for (int i = 0; i < suppExe.length; i++) {
System.out.println("Suppressed Exceptions:");
System.out.println(suppExe[i]);
}
}
}
}
//Do something
//Close my Resource
//Close my Resource
//Suppressed Exception Array length = 2
//Suppressed Exceptions:
//org.example.SecondError
//Suppressed Exceptions:
//org.example.SecondError
첫 번째 에러가 발생하고 두 번째 에러가 발생했을 때 두 번째 에러를 Suppressed 로 쌓아두고 첫 번째 에러를 먼저 보여준다. 또한 catch 구문을 통해 Exception 을 받아 처리할 수도 있으며 여기서 getSuppressed API 를 통해 에러 로그들을 소스코드 단에서 직접 핸들링할 수도 있다.
"try-with-resources 구문은 가독성도 훌륭할 뿐 아니라 디버깅하기도 쉽다."
'독후감 > Effective JAVA' 카테고리의 다른 글
[Effective JAVA] 11 "equals를 재정의하려거든 hashCode도 재정의하라" (0) | 2022.05.03 |
---|---|
[Effective JAVA] 10 "equals는 일반 규약을 지켜 재정의하라" (0) | 2022.04.30 |
[Effective JAVA] 8 "finalizer 와 cleaner 사용을 피하라" (0) | 2022.04.29 |
[Effective JAVA] 7 "다 쓴 객체 참조를 해제하라" (0) | 2022.04.28 |
[Effective JAVA] 6 "불필요한 객체 생성을 피하라" (0) | 2022.04.28 |