JAVA——Scanner类绑定System.in后调用close()方法所引发的错误及其解决方案

基本概念

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.inin于是一个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

http://www.imooc.com/wenda/detail/569103

https://blog.csdn.net/biao_suki/article/details/45357425

发布了1371 篇原创文章 · 获赞 237 · 访问量 33万+

猜你喜欢

转载自blog.csdn.net/weixin_43272781/article/details/104169128