sitelink1 | |
---|---|
sitelink2 | |
sitelink3 | |
sitelink4 | |
sitelink5 | |
sitelink6 |
톰캣에서 NoSuchElementException 에러가 발생해서 1시간동안 원인을 찾지 못해 포기했다가
하루가 지나 레퍼런스 몇개 보다보니 문득 감이 잡히는 지점이 발견되었고 결국 오류를 잡을 수 있었다
NoSuchElementException 은 API를 찾아보면 if the iteration has no more elements 라고 나온다
next 함수로 다음 데이터를 가져오지 못할때 발생한다고 하는데
톰캣을 실행한 런타임 시점에서만 발생하고 톰캣 콘솔창 출력에서는 next() 함수의 다음 라인을 가리킨다는게 함정이었다
다음과 같이 HashMap 데이터를 두번 순회하는 코드를 작성하였다
Task task = null;
Iterator keyIterMoveTo = taskMap.keySet().iterator();
while (keyIterMoveTo.hasNext()) {
Object moveKeyObj = keyIterMoveTo.next();
task = taskMap.get(moveKeyObj);
... ... ...
}
Iterator keyIterToApply = taskMap.keySet().iterator();
while (keyIterToApply.hasNext()) {
Object applyKeyObj = keyIterToApply.next();
task = taskMap.get(applyKeyObj);
... ... ...
}
Iterator 객체를 중복해서 접근하지도 않고 next() 취한 객체도 다른 변수에 담았다
Exception 에러메세지는 위에 붉은색으로 표시한 부분이 아닌 그 다음 라인의 HashMap의 get() 함수 호출 라인을 가리키고 있었다
문제가 HashMap의 get() 함수에 있는게 맞긴 했는데 오류는 Iterator 의 next() 에서의 Exception 이 발생하는게 의문이긴 하지만
어쨌든 다음과 같은 방법으로 해결이 가능했다
Task task = null;
Iterator keyIterMoveTo = taskMap.keySet().iterator();
while (keyIterMoveTo.hasNext()) {
Object moveKeyObj = keyIterMoveTo.next();
task = (Task) taskMap.get(moveKeyObj);
... ... ...
}
Iterator keyIterToApply = taskMap.keySet().iterator();
while (keyIterToApply.hasNext()) {
Object applyKeyObj = keyIterToApply.next();
task = (Task) taskMap.get(applyKeyObj);
... ... ...
}
HashMap에서 get()한 오브젝트에 강제 형변환을 걸어주었다
JDK8버전을 사용하고 있는데 이전 버전에서도 그랬는지 모르겠지만 Iterator의 next() 함수와 HashMap 의 get() 함수의 return 객체들은 모두 Object 인데
위와 같이 형변환이 없으면 저 부분에서 문법오류를 넣어주면 안될려나? 라는 아주 아주 사소한 의문이 들긴했다 (쓸데없음)
여하튼 다음부턴 NoSuchElementException 에러가 발생하면 다음과 같은 절차로 코드를 살펴보자
1. Iterator를 전체 순환후 혹시나 next() 함수를 또 호출하게 실수하지 않았는지?
2. 위와 같이 중복 순환시 실수로 동일 Iterator객체를 접근하지는 않았는지?
3. 마지막으로 위와 같이 next() 로 가져온 key값으로 HashMap에서 get() 한 오브젝트에서 올바른 클래스로 형변환은 했는지?
자바 개발 15년간 매번 1번, 2번만 신경썼는데 3번과 같은 복병이 있을줄은 몰랐다