2025. 11. 18. 08:01ㆍJava
interface default Method 에서 BufferedReader 로 라인수만큼 읽어내기
나는 자바 프로젝트에서 interface 를 자주 쓰는 편이다. 웹 프로젝트가 아닌 일반 응용 소프트웨어 개발에서 말이다.
자바 1.8 부터 interface 에서 default 예약어를 앞에 붙이면 선언만 가능했던 메소드를 정의할 수 있게 되었다. 즉 텍스트 처리 유틸리티 클래스를 interface 로 정의하는 것이다. 유틸티티 계통은 대부분 class 에서 static 으로 메소드를 정의해서 Util.processStr() 처럼 쓰는데, interface 에 정의하면 클래스 정의할 때만 implements 뒤에 써준 후로는 메소드만 호출해주면 되기 때문에 편리하다. 다만 interface 만이 가진 제약성이 있으므로 주의해서 쓰면 된다.
public interface Util {
String EMPtY_STR = "";
String NL_STR = "\n";
default String readByRowCount(String contentStr, int lineCnt) {
if (contentStr == null || contentStr.trim().length() == 0) {
return EMPTY_STR;
}
int cnt = 0;
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new StringReader(contentStr));
while (reader.ready()) {
++cnt;
if (lineCnt == 0 || cnt <= lineCnt) {
System.out.println("cnt= " + cnt);
builder.append(reader.readLine()).append(NL_STR);
}
}
reader.close();
}
}
이렇게 작성하고 실행해보았다.
public class Test imeplements Util {
public static main(String[] args) {
new Test();
}
public Test() {
String wantedStr = readByRowCount("ABC.xml", 5);// <-- 이렇게 호출
}
}
원하던 결과가 아니었다.
cnt= 1
cnt= 2
cnt= 3
cnt= 4
cnt= 5
(여기까지만 출력되길 바랬는데... 아니 이게 무슨 일이지??!!!)
cnt= -2147483648
cnt= -2147483647
cnt= -2147483646
cnt= -2147483645
.
.
.
원하지 않는 음수가 계속 출력되는 것이었다. 5까지만 나오고 끝나야 되는데, 본래 기능은 텍스트 파일에서 한 줄씩 읽어서 총 5줄만 뽑아내는 것이었는데, 배포해서 잘 쓰고 있던 프로그램에서 유틸리티하나 건드렸다가 이런 버그가 발생하다니!! 이걸 고치다가 야근시간만 더 늘어날 것 같고, 안되겠다. 지피티에게 물어봐야지!! 후덜덜....
[++number returns smaller than zero in java interface default method what's wrong] 으로 급히 검색한 결과 답변은 :
Integer.MAX_VALUE 를 넘어가면 말그대로 overflow 가 발생해서 반대값인 음수(-2147483648)가 나온다... 이건 내가 의도한바가 아니었고, 두 번째 답변은 interface 에서 default 메소드는 멤버 변수를 가질 수 없다..... 여기서 아차!! 내가 잠시 간과하고 있었던 것이었다. interface 는 final 기능이 자동적용되어서 값을 연속으로 할당할 수 있는(즉, 변하는 인수) 변수를 가질 수 없고 상수만 가능한데 자주 쓰던 카운트 개념을 급히 넣어서 만드려고 했던 것이다.
이걸 해결하는 방법 중의 하나는 외부에 이 기능을 수행하는 유틸 class 를 만들어서 호출하는 것인데, 이 기능 한 개 때문에 비효울적이 될 수 없어서 apache common 라이브러리 메소드를 찾았더니 IOUtils 를 활용하는 방법과 더불어 이런 서드 파티 유틸리티를 활용하지 않고도 해결하는 방법으로 BufferedReader 에서 자체적으로 제공하는 메소드가 나왔다. 본 게시글에서 설명하려던 바로 그 방법이다.
public interface Util {
String EMPTY_STR = "";
String NL_STR = "\n";
default String readByRowCount(String contentStr, int lineCnt) {
if (contentStr == null || contentStr.trim().length() == 0) {
return EMPTY_STR;
}
int cnt = 0;
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new StringReader(contentStr));
// 이렇게 고쳤다. 자바 1.8부터 스트림 api 가 추가 되어서 아래와 같이 사용가능하다.
List<String> gotLines = reader.lines().limit(lineCnt).collect(Collectors.toList());
if (gotLines != null && gotLines.size() > 0) {
for (String str : gotLines()) {
builder.append(str).append(NL_STR);
}
}
reader.close();
return builder.toString();
}
}
BufferedReader.lines() 가 전체 내용을 가져오는
'Java' 카테고리의 다른 글
| eGov 공통 구성하기 (0) | 2024.07.24 |
|---|---|
| JSTL 로 넘어온 모델 변수값 확인하기 (0) | 2023.08.01 |
| [자바] JSON parsing (0) | 2023.08.01 |
| [Maven] ojdbc 의존성 (0) | 2023.08.01 |
| Jedis - Redis(레디스) 자바 API (0) | 2023.08.01 |