Java 예외 - try with resources 문법
애플리케이션에서 외부 자원을 해제하는 방법으로 try ~ catch ~ finally 소개하였다.
이번에는 try ~ with ~ resources 편의 기능으로도 외부 자원을 무조건 해제할 수 있다.
finally 사용
try {
// 정상 흐름
} catch(... ...) {
// 예외 흐름
} finally {
// 정상 흐름 이후 반드시 호출함
}
try ~ with ~ resources
외부 자원 해제에는 반납하는 패턴이 있어야하며, 기준에는 try {} finally {}
문법으로 정의할 수 있었다.
자바 7부터는 try - with - resources 지원 하는 기능은 try 에서는 자원을 함께 사용하고 try가 종료하면 반드시 자원을 반납하라는 의미이다.
그리고 자바는 AutoCloseable 인터페이스가 있으므로 이것을 사용한다.
AutoCloseable (Java Platform SE 8 )
AutoCloseable.interface
public interface AutoCloseable {
void close() throws Exception;
}
인터페이스 구현은 try with resources 사용 시 try 끝날 시점에 AutoCloseable 호출한다.
다음으로 try with resources 구문을 사용 예제이다.
try (Network clien = new Network(address)) {
// 파라미터처럼 생긴 부분에 자원을 적는다.
}
실습
이전에 작성한 Network 코드를 수정하여 다뤄보도록 한다.
NetworkClient.class
public class NetworkClient implements AutoCloseable {
private final String address;
public boolean connectError;
public boolean sendError;
public NetworkClient(String address) {
this.address = address;
}
public void connect() {
// exception error
if (connectError) {
throw new ConnectException(address, address + " is Connect Open Failed");
}
// Connect Success
System.out.println(address + " Connect Open Success");
}
public void send(String data) {
if (sendError) {
throw new SendException(data, address + " Send Failed" + data);
}
// 전송 성공
System.out.println(address + " Send Message data: " + data);
}
public void disconnect() {
System.out.println(address + " Connect Closed Success");
}
public void initError(String data) {
if (data.contains("error1")) {
connectError = true;
}
if (data.contains("error2")) {
sendError = true;
}
}
@Override
public void close() {
System.out.println("NetworkClient closed");
disconnect();
}
}
- 클래스를 추가로 인터페이스를 상속 받도록 한다. implements AutoCloseable
- close() 인터페이스에서 선언한 메소드는 반드시 오버라이드 해주어야 한다.
이 메소드는 try 가 끝나는 시점에 동작하는 코드이다. - AutoCloseable 의 close() 메소드는 예외를 던지지 않으므로 throws Exception 없어도 된다.
NetworkService.class
public class NetworkService {
public void sendMessage(String data) {
String address = "http://kiioio.com";
try (NetworkClient client = new NetworkClient(address)) {
client.initError(data);
client.connect();
client.send(data);
}
}
}
- try 괄호에 사용할 자원을 선언 및 할당한다.
- try 문이 끝나는 시점에 AutoCloseable.close() 호출하여 자원이 끊어진다.
- catch 문이 없어도 try 블록만으로 close() 호출 성공한다.
참고로 catch 블록을 실행 전에 close() 메소드가 먼저 코드가 동작한다.
try with resources 장점
장점을 나열해보도록 한다.
- 리소스 누수 방지
- 리소스를 모두 닫히도록 보장한다. finally 자원 해제 누락을 예방이 가능하다.
- 코드 간결하고 가독성 향상
- try만 사용하고 명시적인 close() 메소드 호출이 필요없다.
- 한정된 스코프 범위
- 리소스로 사용하는 client 변수의 스코프는 try 블록에서만 사용된다.
- 빠른 자원 해제
- try with resources 구문으로 try 구문이 끝나는 즉시 close() 호출로 외부 자원을 해제한다.
- 기존의 try ~ finally 구문은 모두 호출되어야 자원 해제가 되었다.