基本概念
Java通过系统类System实现标准输入/输出的功能
通过实例化Scanner类的方式实现从键盘的数据输入
问题描述
错误示例一:
import java.util.Scanner;
public class CloseTest {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int a = in.nextInt();
System.out.println(a);
in.close();
Scanner in_2 = new Scanner(System.in);
int b = in_2.nextInt();
System.out.println(b);
in_2.close();
}
}
输入1后的结果:1
Exception in thread "main" java.util.NoSuchElementException
at java.util.Scanner.throwFor(Scanner.java:862)
at java.util.Scanner.next(Scanner.java:1485)
at java.util.Scanner.nextInt(Scanner.java:2117)
at java.util.Scanner.nextInt(Scanner.java:2076)
at test.CloseTest.main(CloseTest.java:13)
错误示例二:
错误示例三:
19行的注释去掉后运行时第22行就会报错
问题分析
以错误示例一为例:
在创建Scanner类对象in后,实现了输入,试图调用close方法关闭输入流,再创建一个新的Scanner对象,
在int b = in_2.nextInt();一句出现错误。
这是因为创建的in和in_2对象都是有System.in封装而来的,虽然是两个独立的对象,但是用的是同一个输入流
补充:System.in 而in于是一个final类型,它一旦被初始化就不能被改变。所以,不过你后面创建多少个Scanner类对象,其实都是返回同一个InputStream流。也就是说,每一次赋给新对象的地址是同一个。
在调用in.close()实际上相当于System.in.close()
对于创建的in_2来说,System.in已经被关闭了。
补充:Scanner类的close()方法会关闭其绑定的输入流。
即:一旦关闭 System.in 流时,后面的对象所用的 System.in 流就是关闭状态。而 System.in 一个final类型,无法获取一个新的 System.in 流
惊喜就会产生!若是不注意可能写了很多代码后才报错,这样就很难找到真正的错误点。
当然也可以通过反编译查看调用情况。
对于错误示例三:console对象绑定的输入流即 System.in ,但是 System.in 已经关闭,导致抛出异常。
解决方案
方法一:
在所有其他的类中不使用使用close()方法
然后在包含主函数的类中创建Scanner对象,在代码的最后调用close()
参考文章
https://www.cnblogs.com/caoshuiping/p/11286265.html
https://blog.csdn.net/qq_35029061/article/details/85525157
https://blog.csdn.net/daiidai/article/details/80716312