热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

调用scanner.close()报错Java.io.Exception:Streamclosed;的原因分析

引言:想对比用于控制台输入的Scanner和BufferedReader,因此放在同一个方法中,之前学习或者使用时没有特别注意过要不要在使

引言:想对比用于控制台输入的Scanner和BufferedReader,因此放在同一个方法中,之前学习或者使用时没有特别注意过要不要在使用完后关闭Scanner,最初根据Eclipse的提示,在使用完Scanner后调用了close(),可是当我再次运行的时候,直接影响到后面InputStreamReader,然后分析原因:从第19行开始,后面的代码都没有用到Scanner,理论上没问题的,然后再看了看,Scanner中有用到System.in,InputStreamReader中也有用到System.in,出问题应该就在System.in了。

 

package com.temp;import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Scanner;public class Test {public static void main(String[] args) throws Exception{// TODO Auto-generated method stubScanner scanner = new Scanner(System.in);System.out.println("please input a Integer number");int number = scanner.nextInt();System.out.println("your input is " + number);// scanner.close();InputStreamReader inputstreamreader = new InputStreamReader(System.in);BufferedReader bufferReader = new BufferedReader(inputstreamreader);System.out.println("please input your info");String string = bufferReader.readLine();System.out.println("your information is " + string);}}

在我们写代码的时候,如果申明后用完Scanner后没有及时关闭,IDE会自动提示我们需要关闭流

(Eclipse IDE会有提示,Intellij IDEA没有提示)

如果我们没有手动关闭,虽然Scanner对象最终会进入被回收的队列中,但不是立刻回收,这会造成内存占据。

为了节省内存我们一般在使用完Scanner后会调用scanner.close();来关闭输入流。

下面开始分析:

1、查看close()方法的源码

/*** Closes this scanner.**

If this scanner has not yet been closed then if its underlying* {@linkplain java.lang.Readable readable} also implements the {@link* java.io.Closeable} interface then the readable's close method* will be invoked. If this scanner is already closed then invoking this* method will have no effect.**

Attempting to perform search operations after a scanner has* been closed will result in an {@link IllegalStateException}.**/private boolean closed = false; // Boolean indicating if this scanner has been closedprivate Readable source; // The input sourcepublic void close() {if (closed)return;if (source instanceof Closeable) {try {((Closeable)source).close();} catch (IOException ioe) {lastException = ioe;}}sourceClosed = true;source = null;closed = true;}

在这源码中我们可以看到source就是输入的source,对于Scanner输入的source就是System.in,close()方法中有判断

if (source instanceof Closeable)

instanceof 关键字用法:instanceof 是 Java 的保留关键字。它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。

因此如果source是Closeable的一个实例,那么source也会被关闭。

 

2、查看System源码(第77行开始)

/*** The "standard" input stream. This stream is already* open and ready to supply input data. Typically this stream* corresponds to keyboard input or another input source specified by* the host environment or user.*/public final static InputStream in = null;

注释部分翻译:

“标准”输入流。该流已经打开并准备提供输入数据。通常,此流对应于键盘输入或由主机环境或用户指定的另一个输入源。

----我们还注意到InputStream是被final修饰的----

 

3、查看InputStream源码

我们发现InputStream实现了Closeable接口

(也可直接查看JDK官方文档)

综上,由于InputStream实现了Closeable接口,因此InputStream会被关闭,但是同时InputStream是被final修饰过的,只能被实例化一次,因此我们后面代码再使用System.in也依然是被关闭的。

因此在后面使用的时候会报错:Stream closed

为了避免报错,只好在最后再关闭了


推荐阅读
author-avatar
小旋律丶_409
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有