[Share] Try-with-resources
boohyunsik opened this issue · comments
Topic
3장 템플릿 첫 부분에 try-catch가 나와서 참고가 될 만한 try-with-resources에 대해 소개해드리고자 합니다.
Detail
Java를 이용해 외부 자원에 접근하는 경우 한가지 주의해야할 점은 외부자원을 사용한 뒤 제대로 자원을 닫거나 해제해야 한다는 점입니다.
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("test.txt");
} catch(IOException e) {
System.out.println("error : " + e.getMessage());
} finally {
fis.close();
}
}
그러나 위 코드에서 fis.close()
도 IOException
을 던지기 때문에 다음과 같은 코드가 됩니다.
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("test.txt");
} catch(IOException e) {
System.out.println("error : " + e.getMessage());
} finally {
try {
fis.close();
} catch(IOException e) {
// Handle error...
}
}
}
또한 test.txt
파일이 없는 경우는 fis
가 null
일 것이기 때문에 null check도 해줘야 합니다.
public static void main(String[] args) {
FileInputStream fis = null;
try {
fis = new FileInputStream("test.txt");
} catch(IOException e) {
System.out.println("error : " + e.getMessage());
} finally {
try {
if (fis != null) {
fis.close();
}
} catch(IOException e) {
// Handle error...
}
}
}
코드가 매우 지저분해집니다. 이를 해결하기 위해 JDK 1.7부터는 다음과 같은 인터페이스가 추가되었습니다.
/**
* @author Josh Bloch
* @since 1.7
*/
public interface AutoCloseable {
void close() throws Exception;
}
(저자 Josh Bloch는 Effective Java의 저자입니다.)
이 인터페이스 추가와 더불어 try절에 소괄호가 들어가는 문법이 추가되었습니다.
try(FileInputStream fis = new FileInputStream("test.txt") {
// Do something if success
} catch(IOException e) {
// Handle error...
}
다음과 같이 깔끔하게 코드를 작성할 수 있고, close()
를 호출하지 않아도 성공적으로 실행했을때나, Exception이 발생했을때 모두 자원을 해제할 수 있습니다.
이제 봤는데 내용 좋네요
몰랐습니다..
공유 감사해요!
오 신기하네요. 완전 꿀팁!
좋은 글 감사합니다!
신기해서 try-with-resource statement
에 대해 찾아보다가 추가 내용이 있어 공유합니다!
try-with-resource
는try
에 자원 객체(AutoCloseable
인터페이스를 구현한 객체)를 전달하여try
코드 블록이 끝나면 자동으로 자원을 종료함.
try (SomeResource resource = getResource()) {
use(resource);
} catch(...) {
...
}
try()
안에 여러 개의 자원 객체를 전달할 수 있음.
try(Something1 s1 = new Something1();
Something2 s2 = new Something2()) {
...
} catch(...) {
...
}
try
블록과finally
블록에서 동시에 예외가 발생했을 경우, 기존try-catch-finally
구문은finally
블록에서 발생한 예외를 throw 하지만,try-with-resource
구문은try
블록의 예외를 throw 함.
static String useTry(String path) throws IOException {
BufferedReader br = new BufferedReader(new FileReader(path));
try {
return br.readLine();
} finally {
if (br != null) br.close();
}
}
위 코드에서
try {
return br.readLine();
}
이 부분(br.readLine()
)과
finally {
if (br != null) br.close();
}
이 부분(br.close()
)에서 동시에 예외 발생할 수 있음. 이런 경우 br.close()
의 예외를 throw 함.
그러나 try-with-resource
구문은 다름.
static String useTryResource(String path) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return br.readLine();
}
}
위 코드에서
return br.readLine();
try
블럭 부분(br.readLine()
)과
try (BufferedReader br = new BufferedReader(new FileReader(path)))
try resource
부분(new FileReader()
)에서 동시에 예외 발생할 수 있음. 이런 경우 br.readLine()
의 예외를 throw 함.
@hihiboss 마지막 3번에서 br.readline() 에러가아니라 new FileReader()의 exception 을 throw하는게 맞지않앙??
그리고 다들 봣을수있지만 위의 예제처럼 중첩접근에서의 close() 호출순서에대해서
https://multifrontgarden.tistory.com/192
여기 잘나와있어요~ autocloseable 을 impl 할일 있거나 close가 어떻게 각각 일어나는지 궁금하면 참고 하세요