![[JAVA] 리소스(resource) 자동 닫기](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrmTb3%2FbtsnEK9soVx%2F4Q6eYkiIwV6gUnLEW3ow70%2Fimg.jpg)
[JAVA] 리소스(resource) 자동 닫기Language/Java2023. 7. 25. 00:45
Table of Contents
이 게시글은 이것이 자바다(저자 : 신용권, 임경균)의 책과 동영상 강의를 참고하여 개인적으로 정리하는 글임을 알립니다.
- 리소스란 데이터를 제공하는 객체(DB 등)를 뜻한다.
- 리소스를 사용하기 위해선 열어야 하고, 사용이 끝나면 반드시 닫아야 한다.
- 리소스를 사용하고 닫지 않으면 불안정한 상태로 남게 된다.
try-catch-finally문
리소스를 자동으로 닫는 기본적인 방법은 try-catch-finally문에서 finally 부분에 리소스를 닫는 코드를 넣어주면 된다.
finally는 예외가 발생하든 안 하든, 메소드가 return문을 만나도 무조건 실행되기 때문이다.
FileInputStream fis = null;
try {
fis = new FileInputStream("file.tsxt");
} catch(IOException e) {
//예외 처리 코드 작성
}finally {
fis.close(); //리소스 닫기
}
try-with-resources문
try-catch-finally문과 다르게 finally문을 작성하지 않아도 된다.
이 또한 예외 발생 여부와 상관없이 리소스를 자동으로 닫아준다.
try괄호에 리소스를 여는 코드를 작성하면 try 블록이 정상적으로 실행을 완료했거나 도중에 예외가 발생하면 자동으로 리소스의 close() 메소드가 호출된다.
하지만 try-with-resources문을 사용하려면 리소스는 java.lang.AutoCloseable 인터페이스를 구현하고 해당 인터페이스의 close() 메소드를 오버라이딩(재정의) 해야 한다.
java.lang.AutoCloseable 인터페이스는 자바가 기본적으로 제공한다.
따라서 우리는 구현 객체만 만들면 된다.
복수 개의 리소스를 사용해야 한다면 아래와 같이 try() 괄호 안에 세미콜론으로 구분해서 리소스를 여는 코드를 작성하면 된다.
Java 9 버전 이후부터는 외부 리소스 변수를 사용할 수 있다.
public class Main { public static void main(String[] args) { MyResource fis1 = new MyResource("file1.txt"); MyResource fis2 = new MyResource("file2.txt"); try (fis1; fis2){ }catch(IOException e) { //예외 처리 코드 작성 } } }
아래의 예제는 try-with-resources문을 이용하여 제대로 리소스를 닫을 수 있는지를 확인하는 예제이다.
결과를 확인하면 제대로 예외가 발생해도 close() 메소드가 자동으로 호출되어 리소스를 자동으로 닫을 수 있다는 것을 확인할 수 있다.
MyResource.java
public class MyResource implements AutoCloseable {
private String name;
public MyResource(String name) {
this.name = name;
System.out.println("[MyResource(" + name + ") 열기]");
}
public String read1() {
System.out.println("[MyResource(" + name + ") 읽기]");
return "100";
}
public String read2() {
System.out.println("[MyResource(" + name + ") 읽기]");
return "abc";
}
@Override
public void close() throws Exception {
System.out.println("[MyResource(" + name + ") 닫기]");
}
}
Main.java
public class Main {
public static void main(String[] args) {
try (MyResource res = new MyResource("A")) {
String data = res.read1();
int value = Integer.parseInt(data);
} catch(Exception e) {
System.out.println("예외 처리: " + e.getMessage());
}
System.out.println();
///////////////////////////////////////////////////
try (MyResource res = new MyResource("A")) {
String data = res.read2();
//NumberFormatException 발생
int value = Integer.parseInt(data);
} catch(Exception e) {
System.out.println("예외 처리: " + e.getMessage());
}
System.out.println();
///////////////////////////////////////////////////
try (
MyResource res1 = new MyResource("A");
MyResource res2 = new MyResource("B")
) {
String data1 = res1.read1();
String data2 = res2.read1();
} catch(Exception e) {
System.out.println("예외 처리: " + e.getMessage());
}
System.out.println();
///////////////////////////////////////////////////
MyResource res1 = new MyResource("A");
MyResource res2 = new MyResource("B");
try (res1; res2) {
String data1 = res1.read1();
String data2 = res2.read1();
} catch(Exception e) {
System.out.println("예외 처리: " + e.getMessage());
}
}
}
/*
[MyResource(A) 열기]
[MyResource(A) 읽기]
[MyResource(A) 닫기]
[MyResource(A) 열기]
[MyResource(A) 읽기]
[MyResource(A) 닫기]
예외 처리: For input string: "abc"
[MyResource(A) 열기]
[MyResource(B) 열기]
[MyResource(A) 읽기]
[MyResource(B) 읽기]
[MyResource(B) 닫기]
[MyResource(A) 닫기]
[MyResource(A) 열기]
[MyResource(B) 열기]
[MyResource(A) 읽기]
[MyResource(B) 읽기]
[MyResource(B) 닫기]
[MyResource(A) 닫기]
*/
'Language > Java' 카테고리의 다른 글
[JAVA] API Document (0) | 2023.07.27 |
---|---|
[JAVA] 사용자 정의 예외 (0) | 2023.07.26 |
[Java] Getter와 Setter 메소드 (0) | 2023.07.24 |
[JAVA] 리플렉션(Reflection)과 어노테이션(Annotation) (0) | 2023.07.23 |
[JAVA] 전이 의존과 집합 모듈 (0) | 2023.07.22 |