DEV/Java

[java] NoSuchElementException 예외의 이해와 발생사례

Bi3a 2023. 10. 25. 02:42

목차
반응형

NoSuchElementException에 대한 이해
java 기초 깨부시기


NoSuchElementException

없는 공간에서 없는 값을 꺼낼 때 발생하는 에러입니다.
주요 발생 이유 :
1. Scanner, BufferedReader 등 System.in을 통해 사용자 입력을 받는 객체 사용 시 발생
2. Iterator 사용이 가능한 Collection 객체에서 순회를 잘못할 시 발생

 

System.in을 통해 사용자 입력을 받는 객체 사용 시 발생 사례 : No line found

 

java
닫기
import java.util.Scanner;
public class Main{
public static void main(String[] args) {
Main main = new Main();
main.readA();
main.readB(); // error : scanner가 닫혀있는 상태로 실행
}
public void readA(){ // Scanner을 사용하는 메소드 a
Scanner sc = new Scanner(System.in);
sc.nextLine();
sc.close(); // scanner close
}
public void readB(){ // Scanner를 사용하는 메소드 b
Scanner sc = new Scanner(System.in);
sc.nextLine();
}
}

 

일반적으로 두 개 이상의 메서드에서 사용자 입력을 받는 객체를 각각 불러 각 메서드에서 실행하다가 이후 메서드 실행 전 해당 객체가 close()로 닫혀 있는 경우 `NoSuchElementException : No line found` 예외를 발생시킵니다.

 

예외가 발생하는 이유를 예시로 설명한 사용자의 입력을 받는 Scanner 객체를 예시로 설명하겠습니다.

  • `Scanner(System.in)` : 실행 프로그램에서 하나만 생성되며, 여러개의 객체들이 공유함
  • `Scanner.close()` : 한 객체라도 닫으면 여러 객체가 공유하는 System.in도 닫히므로 이후에 스캐너 실행 시 예외 발생
  • 따라서 `System.in`을 사용하는 객체는 프로그램에서 하나만 생성하고 공유하는 것을 권장합니다.

 

 

Iterator를 통해 Collection 순회 시 발생 사례

 

java
닫기
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Main{
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>(List.of(1,2,3,4,5));
Iterator<Integer> iter = list.iterator();
while(iter.hasNext()){
iter.next();
System.out.println(iter.next()); // out: 2, 4, 쾅(error)
}
}
}

Iterator를 통해 Collection을 순회하는 도중 `NoSuchElementException` 가 발생하는 코드 예시입니다.

해당 코드는 while문에서 1회 순회마다 `next()`를 두번씩 호출하고 있습니다.

따라서 `iter.hasnext()``next()`의 순회속도를 따라가지 못하고 발생한 예외입니다.

 

 

해결방법 : `hasnext()`를 조건문으로 세우는 while loop의 내부에는  `next()`를 한 번만 실행합니다.

java
닫기
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Main{
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>(List.of(1,2,3,4,5));
Iterator<Integer> iter = list.iterator();
while(iter.hasNext()){
// next() 한번만 실행
System.out.println(iter.next()); // out: 1, 2, 3, 4, 5
}
}
}
반응형