최근에 FileReader, BufferedReader를 공부하면서, 버퍼의 자원해제 관련하여 새로 알게된 내용이 있어 남겨둔다
= FileReaderTests.java
package com.ys.test.lab;
import com.ys.test.lab.common.File;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class FileReaderTests {
File file;
@BeforeEach
public void load() {
this.file = new File();
}
@Test
public void getMemberTestOne() {
List<String> files = file.getFileReader("src/main/resources/contents/members.csv");
String[] memberInfo = memberArr(files.get(0));
assertEquals("xggames", memberInfo[0]); // 회원ID
assertEquals("백엔드개발자", memberInfo[1]); // 회원의 직업
}
private String[] memberArr(String memberStr) {
return memberStr.split(",");
}
}
= File.java (AS-IS)
package com.ys.test.lab.common;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
// 파일을 읽어들이는 Class
public class File {
public List<String> getFileReader(String fileUrl) {
FileReader fileReader;
BufferedReader bufferedReader;
try {
fileReader = new FileReader(fileUrl);
bufferedReader = new BufferedReader(fileReader);
List<String> returnList = bufferedReader.lines().collect(Collectors.toList());
fileReader.close();
bufferedReader.close();
return returnList;
} catch (IOException e) {
System.out.println(e.getMessage());
}
return new ArrayList<>();
}
}
FileReaderTests.java의 테스트케이스에서 File.java에 보면 FileReader와 BufferedReader를 사용하고, 자원을 해제처리하였다. 그런데 만약 중간에 Exception이 발생하게되면 close()를 하지못하는 상황이 생기고, 메모리 누수 및 특정 프로그램의 독점으로 인해 객체가 올바르게 동작하지 않을 수도 있다. 물론 CG가 결국 메모리를 회수해가긴 하지만, 그 시점이 언제인지도 불투명하므로 가급적이면 자원의 해제처리가 필요하다.
이러한 문제를 java7부터 지원하는 Try-with-resources를 사용하여 자동으로 자원해제처리할 수 있다.
= File.java (TO-BE)
package com.ys.test.lab.common;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class File {
public List<String> getFileReader(String fileUrl) {
try(
FileReader fileReader = new FileReader(fileUrl);
BufferedReader bufferedReader = new BufferedReader(fileReader);
) {
return bufferedReader.lines().collect(Collectors.toList());
} catch (IOException e) {
System.out.println(e.getMessage());
}
return new ArrayList<>();
}
}
=> try문에 괄호를 열어 버퍼 객체생성 코드를 넣어준다. 자원의 사용이 끝나면, 자동으로 닫아주게 된다.
덤으로 코드도 깔끔해진다.
try-with-resources 사용조건
try문에 입력할 리소스 객체는 java.lang.AutoCloseable 인터페이스를 구현하고 있어야 한다는 조건이 필요하다. AutoCloseable에는 close() 메소드가 정의되어 있는데, try-with-resources는 이 close() 메소드를 자동으로 호출한다.
(위의 FileReader와 BufferedReader는 상위에 Reader 추상화 클래스를 상속받아 구현하는데, Reader에서 Closeable을 implements하고, Closeable 인터페이스가 AutoCloseable을 상속받기때문에, close()가 호출되며, 자원해제처리가 된다)
더 알아보기 (Java Oracle 공식문서)
참고자료
'JAVA' 카테고리의 다른 글
Java - Checked Exception VS Unchecked Exception (0) | 2022.03.10 |
---|---|
Java - 커맨드패턴(Command Pattern) (0) | 2022.02.22 |
Java - 정규표현식 정리 (0) | 2022.02.07 |
Java - 자료구조와 컬렉션 프레임워크 (0) | 2022.01.23 |
Java - 빌더 패턴(Builder Pattern) (0) | 2022.01.13 |