티스토리 뷰
[이펙티브 자바 3/E] 아이템 9 : try-finally 보다는 try-with-resources를 사용하라
핵심
close 메서드를 호출해 직접 닫아줘야하는 자원에 "try-with-resources"를 적용해 안전하게 닫아주자!!
예) InputStream, OutputStream, java.sql.Connection 등
** 자원을 닫지 않으면 성능 문제로 이어질 수 있다.
try-finally (Java7 이전)
변수1 = null;
변수2 = null;
try {
변수1 = new 자원객체1();
변수2 = new 자원객체2();
변수1.작업();
변수2.작업();
...
} finally {
if (변수1 != null) 변수1.close();
if (변수2 != null) 변수2.close();
}
✅ 어떤 경우에도 자원을 반납하도록 구현하기위해 fianlly를 사용하게 된다.
✅ null 여부를 추가로 검사해야한다.
✅ close 해주는 걸 잊으면 그냥 끝..
✅ 디버깅의 어려움을 유발한다.
try-with-resources (Java7 이후)
try (변수1 = new 자원객체1();
변수2 = new 자원객체2()) {
...
}
try-with-resources는 try(...)에서 선언된 객체들에 대해 try가 종료될 때 자동으로 close를 호출하여 자원을 해제해주는 기능을 제공한다.
✅ Java7부터 제공한다.
✅ 이때 해제하려는 자원의 객체에는 AutoCloseable 인터페이스가 구현되어 있어야한다. (아이템8 참고)
위의 경우가 아니라면 무조건 try-with-resources를 사용하자!!
✅ 짧고 읽기 수월해진다.
✅ close를 잊을 일이 없다.
✅ 문제를 진단하기 좋아진다.
✅ 디버깅의 어려움을 해소한다.
** IntelliJ에서도 다음과 같이 try-fianlly로 자원을 해제할 경우 경고를 띄우며, try-with-rewources로의 변경을 권장하고 있다.
디버깅의 어려움을 유발하고 해소한다..?
try-finally (Java7 이전)
예외는 try 블록과 finally 블록 모두에서 발생할 수 있다.
이럴 경우 fianlly 블록에서 발생한 예외만 남게되고 try 블록에서 발생한 예외는 알 수 없게 된다.
@Test
void throwExceptionTryFinally() throws IOException {
FileInputStream is = null;
BufferedInputStream bis = null;
try {
is = new FileInputStream("/Users/ellie/MyData/woowacourse/file.txt");
bis = new BufferedInputStream(is);
int data = -1;
while ((data = bis.read()) != -1) {
System.out.print((char) data);
}
throw new IOException("try에서 에러 발생");
} finally {
if (is != null) {
is.close();
}
if (bis != null) {
bis.close();
}
throw new IOException("finally에서 에러 발생");
}
}
try-with-resources (Java7 이후)
try 블록과 close에서 모두 예외가 발생할 수 있지만 try 블록에서 발생한 예외가 기록된다.
이때 close에서 발생한 예외는 숨겨지며, 스택 트레이스에 “Suppressed(숨겨짐)” 키워드로 출력된다.
public class CustomResource implements AutoCloseable {
public void doSomething() {
System.out.println("Do something...");
}
@Override
public void close() {
System.out.println("CustomResource.close() is called");
throw new IllegalArgumentException("close에서 에러 발생");
}
}
@Test
void throwExceptionTryWithResources() {
try (CustomResource cr = new CustomResource()) {
cr.doSomething();
throw new IOException("try에서 에러 발생");
} catch (Exception e) {
e.printStackTrace();
}
}
Ref.
https://devlog-wjdrbs96.tistory.com/116
https://codechacha.com/ko/java-try-with-resources/
'Backend > Java' 카테고리의 다른 글
생성자 대신 정적 팩터리 메서드를 고려하라 (0) | 2022.02.28 |
---|---|
Unmodifiable Collection (0) | 2022.02.28 |
동일성(Identity) vs. 동등성(Equality) (feat. equals(), hashCode()) (0) | 2022.02.25 |
Null vs. Empty vs. Blank (feat. isEmpty, isBlank) (2) | 2022.02.18 |
부생성자에서 주생성자를 호출하라 (0) | 2022.02.17 |