엘리
💡
close
메서드를 호출해 직접 닫아줘야하는 자원에try-with-resources
를 적용해 안전하게 닫아주자!!
- 예) InputStream, OutputStream, java.sql.Connection 등
- 자원을 닫지 않으면 성능 문제로 이어질 수 있다!!
변수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 블록
과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 (변수1 = new 자원객체1();
변수2 = new 자원객체2()) {
...
}
try-with-resources는 try(...)
에서 선언된 객체들에 대해 try
가 종료될 때 자동으로 close
를 호출하여 자원을 해제해주는 기능을 제공한다.
- Java7부터 제공한다.
- 이때 해제하려는 자원의 객체에는
AutoCloseable
인터페이스가 구현되어 있어야한다. (아이템8 참고)
위의 경우가 아니라면 무조건 try-with-resources를 사용하자!!
- 짧고 읽기 수월해진다.
close
를 잊을 일이 없다.- 문제를 진단하기 좋아진다.
디버깅의 어려움 해소
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();
}
}
** IntelliJ에서도 다음과 같이 try-fianlly로 자원을 해제할 경우 경고를 띄우며, try-with-rewources로의 변경을 권장하고 있다.