Exception in thread "main" java.util.NoSuchElementException
public static void main(String[] args) {
add();
sub();
}
public static void add() {
Scanner scanner = new Scanner(System.in);
int number1 = scanner.nextInt();
int number2 = scanner.nextInt();
System.out.println(number1 + number2);
scanner.close();
}
public static void sub(){
Scanner scanner = new Scanner(System.in);
int number1 = scanner.nextInt();
int number2 = scanner.nextInt();
System.out.println(number1 - number2);
scanner.close();
}
자주 사용하는 Scanner
에대해 잘 알고 있다고 생각했다. 위의 코드를 작성하고 당연히 잘 실행될 줄 알았는데 에러가 발생했다.. 디버깅을 해보니 add()
실행 후 sub()
에서 int number1 = scanner.nextInt();
행에서 에러가 발생했다. Scanner
의 close()
실행 후에 System.in
도 같이 닫아버려서 생기는 문제인 것 같았다.
public void close() {
if (closed)
return;
if (source instanceof Closeable) {
try {
((Closeable)source).close();
} catch (IOException ioe) {
lastException = ioe;
}
}
sourceClosed = true;
source = null;
closed = true;
}
closed
와 source
의 값에 따라 결과 값이 달라진다. 그렇다면 closed
와 source
값이 무엇인지 Scanner
를 추적해보자.
public final class Scanner implements Iterator<String>, Closeable {
...생략
// The input source
private Readable source;
...생략
// Boolean indicating if this scanner has been closed
private boolean closed = false;
...생략
}
closed = false
로 초기화된다.
source
는 다른 곳에서 초기화되는 것 같다. Scanner
의 생성자를 추적해보자.
public Scanner(InputStream source) {
this(new InputStreamReader(source), WHITESPACE_PATTERN);
}
private Scanner(Readable source, Pattern pattern) {
...생략
this.source = source;
...생략
}
public class InputStreamReader extends Reader
public abstract class Reader implements Readable, Closeable
public interface Readable
Scanner scanner = new Scanner(System.in);
로 인해 Readable source = new InputStreamReader(System.in);
로 초기화되고 scanner.close()
를 실행하게 되면 인자로 받은 System.in
을 close
하게 된다.
결과적으로 System.in.close()
를 실행하면 표준 입력 스트림이 닫히고, 이후에는 System.in
을 통해 사용자 입력을 받을 수 없게 된다.
공식문서에서는 아래와 같이 설명한다.