在完成实验的过程中,见到了从未见过的异常:NoSuchElementException。
使用情况是方法A调用方法B,也调用方法C,在B和C中都使用了Scanner,并且都进行了关闭。情况和下面的情况大致相同。
public class testScanner{
class testScanner{
public static void main(String[] args) {
testScanner test = new testScanner();
test.method1();
test.method2();
}
public void method1() {
Scanner inScanner = new Scanner(System.in);
inScanner.next();
inScanner.close();
}
public void method2() {
Scanner inScanner = new Scanner(System.in);
inScanner.next();
inScanner.close();
}
}
错误提示如图所示:
查阅博客(博客园)之后得知,是因为System.in是静态的,当前类中所有System对象共享,在使用close()方法时,会同时关闭Scanner和System.in,而System.in关闭后尝试再次打开得到的值是-1,当第二个函数再次想实例化Scanner时就会抛出NoSuchElementException异常。
在博客园中“IT学习者-螃蟹”的讲解中,看到了这样一段源码:
在Scanner 的readinput方法里面有以下代码:
try {
n = source.read(buf);
} catch (IOException ioe) {
lastException = ioe;
n = -1;
}
if (n == -1) {
sourceClosed = true;
needInput = false;
}
Scanner的next方法中有以下代码:
if (needInput)
readInput();
else
throwFor();
throwFor中的部分代码:
skipped = false;
if ((sourceClosed) && (position == buf.limit()))
throw new NoSuchElementException();
else
throw new InputMismatchException();
梳理一下这个过程:第一次调用method1时,将inScanner关闭,同时也关闭了System.in,因为这个是静态的,所以在这个类中,就被彻底关闭了。之后method2尝试利用其进行读入,因为已经关闭,则读到-1,设置sourceClosed = true;
needInput = false。之后执行throwFor(),position 是当前读取的内容在缓冲区中位置,因为读取的是-1,因此position =0,而buf.limit()也等于0,因此就执行了throw new NoSuchElementException()。