对scanner.close方法的误解以及无法补救的错误
scanner错误关闭导致的异常
public class test2 {
public static void main(String[] args) {
Scanner scanner1 = new Scanner(System.in);
System.out.println("run scanner1.close()");
scanner1.close();
Scanner scanner2 = new Scanner(System.in);
System.out.println("run scanner2.nextLine()");
scanner2.nextLine();
}
}
但是会在scanner2.nextLine()调用时抛出异常
java.util.NoSuchElementException: No line found
原因
下面是scanner的源码
// The input source
private Readable source;
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;
}
所以调用close方法并不仅仅关闭scanner类,同时关闭了初始化时作为参数传入的Readable对象。
在示例代码中scanner1.close();关闭了System.in,所以虽然初始化scanner2没有问题,但是readLine()会报错。
是否可以通过重新开启System.in的方式补救呢?
遗憾的是,至少作为java的使用者来说是不可以的,除非我们能控制jvm运行。
这涉及到System.in是如何开启的,简单来说因为System.in是特殊的系统资源,由jvm负责开启,无法通过java代码重新初始化System.in。
如果查看System.in的代码我们就能发现它通过native方法实现初始化,在native方法中将控制台或文件句柄传输给System.in来完成。
同样的,Systerm.out System.err也是无法重新被开启的资源,对于它们,close方法应该被谨慎的调用。
(ps:实际上有什么原因关闭呢?)
让我们把问题拓展开来
实际上,所有的能够以System.in/out/err为构造器参数的包装器类的close方法都应该被考虑,
可以看到jdk的设计者并没有区别对待普通的流和System.in/out/err,
而包装器类的close方法关闭底层流对于普通流来说是很合理的,因此我们可以推测事实上其他的包装器的close方法也可能导致关闭System.in/out/err。
常用的bufferinputstream就是如此。
jdk7引入的带资源的try语法糖产生隐蔽的问题
jdk7引入的带资源的try语法糖隐式的帮助程序员调用close方法,
遗憾的是该方法也会产生上述问题,甚至更难被发现。
我们有必要积极的关闭不再需要的流嘛?如何对待io.close?如何预防该问题?
从性能的角度来说,积极关闭流是必须的,实际上如果我们使用findbugs等代码规范工具,能发现关闭io是被强烈推荐的。
如果你使用idea的话,建议在close之前,使用快捷键ctrl+b进入close方法的源代码来查看其关闭机制。这种方法非常简便,当然eclipse应该也有插件可以实现类似功能。
我们也可以通过包装System.in/out/err来安全的使用它们,实际上利用装饰器模式,覆盖System.in/out/err的close方法即可。
对scanner.close方法的误解以及无法补救的错误的更多相关文章
- eclipse 从git取项目,导入为maven项目,新加的方法,报加载主类错误
eclipse 从git取项目,导入为maven项目,新加的方法,报加载主类错误 具体描述: 整体编译能够编译成功,但新加一个java,里面创建一个main方法,运行时,报无法加载主类的错误, 整体编 ...
- Java Scanner nextLine方法跳过
问题描述 Scanner使用了nextInt方法的时候,如果接下来要使用nextLine,会获取不到内容 原因 因为Scanner读取用户输入数据,是先判断缓冲区是否含有数据,没有则接收用户输入的数据 ...
- 对 jQuery 中 data 方法的误解
一直以来都认为新版本中 data 是调用 dataset 实现的,对于低版本IE则采用 getAttribute其实一直是我误解了,也不知道最初这个想法是怎么来的.难道我被盗梦了? 今天 谢亮 兄弟和 ...
- Scanner使用方法
import java.util.Scanner; //导入包 public void main (String args[]){ Scanner a=new Scanner(System.in); ...
- Scanner输入方法
输入语句: * import java.util.Scanner; * System.out.println("请输入你想输入的东西:"); * Scanner (自定义)sc = ...
- 关于java和JS中的lastIndexOf方法的误解。
今天看JS的数组的lastIndexOf()方法,看书上的例子,怎么看都觉得不对劲.后来详细读了几遍解释,用java也测试了下,才发现,之前的理解完全是错误的. 上例子: String nums=&q ...
- angularjs 初始化方法执行两次以及url定义错误导致传值错误问题
1.初始化方法执行两次以上的问题定义一个 route.如下所示:.state('main.channelQryDetail', { url:'/channelDetail/:channelNo/:pa ...
- eclipse使用struts2找不到action方法或找不到action的错误记录
在确认web.xml已经配置, 配置好struts.xml , 代码没有报错, jar包没有问题, 服务器也没有问题, 代码逻辑没有问题, 关键字方法名action都没有写错, 可以运行旧的相同的代码 ...
- centos ftp服务器搭建 vsftpd 匿名访问配置方法 ftp 550 Failed to open file 错误处理
vsftpd是linux下常用的ftp服务软件,配置起来其实不复杂,只是网上很多文章,配置后都无法成功.我使用它是用于局域网内部分享文件的,所以使用匿名的方式. ftp本身密码是明文传输的,如果需要安 ...
随机推荐
- aspx页面@Page指令解析
@Page指令位于每个ASP.NET页面的顶部,告诉ASP.NET这个具体页面使用什么属性,以及该页面继承的用户控件.ASP.NET页面@Page指令属性有:AspCompat.Async.Async ...
- Qt中使用Boost
编译BOOST库 bjam stage --toolset=qcc --without-graph --without-graph_parallel --without-math --without- ...
- FC红白机游戏列表(维基百科)
1055个fc游戏列表 日文名 中文译名 英文版名 发行日期 发行商 ドンキーコング 大金刚 Donkey Kong 1983年7月15日 任天堂 ドンキーコングJR. 大金刚Jr. Donkey K ...
- Android零基础入门第59节:AnalogClock、DigitalClock和TextClock时钟组件
原文:Android零基础入门第59节:AnalogClock.DigitalClock和TextClock时钟组件 在前面一期,我们学习了DatePicker和TimePicker,在实际开发中其不 ...
- delphi 获取当前进程的cpu占用率
type TProcessCpuUsage = record private FLastUsed, FLastTime: Int64; FCpuCount:Integer; publ ...
- Linux --- 程序后台运行的几种方法
有时候我们运行一个程序,耗时比较长,所以在快下班的时候或是网络不稳定的时候就比较抓狂. 今天分享几个我在工作中用到的把程序放在后台运行的方法. nohup $ nohup --h Usage: noh ...
- [Erlang-0015][Lager] Erlang日志框架Lager简析
项目地址:https://github.com/basho/lager (欢迎任何形式的转载,但请务必注明出处:http://www.cnblogs.com/liangjingyang)
- MinGW64 how-to(内含编译openssl,libjpeg,libcurl等例子)
Index of contents Setting up the MinGW 64 environment Step 1) building libiconv Step 2) building lib ...
- C++的标准库函数默认都是操作字节,而不是字符,非常痛苦,所以引入了u16string和u32string(Linux上的wchar_t是32位的原因,utf16对unicode的支持是有缺陷的)good
时至今日,字符串使用unicode已经是不需要理由的常识,但对一些有着悠久历史的编程语言来说,这仍然是个头痛的问题.如果抛开第三方库的支持,C++其实并不能实际有效地支持unicode,即使是utf8 ...
- Qt学习虚拟机--基于MSYS2-MinGW环境并带有各种开源的软件库!
Qt学习虚拟机--基于MSYS2-MinGW环境并带有各种开源的软件库!虚拟机地址,VM10和以上:http://pan.baidu.com/s/1slcTA49包含两个分卷压缩包,加起来5GB多. ...