You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

是否应仅实例化一次Scanner?多次实例化报错原因及异常解析

为什么关闭第一个Scanner后,新创建的Scanner会报错?

嘿,这个问题挺有探究精神的,我来一步步给你拆解清楚:

一、报错的核心原因:关闭Scanner会连带关闭System.in

你代码里的第一个scanner.close()是关键!所有基于System.in创建的Scanner,本质上共享同一个底层标准输入流。当你调用close()方法关闭Scanner时,它会自动把关联的System.in也一并关闭——这是Java Scanner的设计逻辑,目的是确保资源被正确释放。

当你后面再创建Scanner sc = new Scanner(System.in)时,这个新Scanner关联的System.in已经是关闭状态了,根本没法从里面读取任何输入,所以调用sc.nextLine()的时候就会直接抛出异常。

如果把第一个scanner.close()注释掉,你的代码就能正常运行(虽然确实冗余,但不会报错)。

二、java.util.NoSuchElementException: No line found是什么意思?

这个异常的字面意思很直白:Scanner尝试读取一行输入,但找不到任何可读取的内容。具体到你的场景,就是因为底层的System.in已经被关闭,没有任何输入流可以读取了,Scanner在执行nextLine()时发现没有数据可读,也无法再获取新数据,就抛出了这个异常。

一般遇到这个异常,要么是输入流已经关闭,要么是输入已经被读完(比如文件读取到末尾),但你的情况属于前者。

三、为什么说Scanner不可克隆?

Scanner不能被克隆主要有两个原因:

  • 没有实现Cloneable接口:Java里要实现克隆,类必须实现Cloneable标记接口,并重写clone()方法,但java.util.Scanner根本没做这件事,直接调用clone()会抛出CloneNotSupportedException。
  • 底层依赖的输入流无法克隆:Scanner依赖的输入流(比如System.in)是有状态的、单向的流——它记录了当前读取的位置,而且流一旦被读取或关闭,状态就不可逆转。你没法复制一个和原输入流状态完全一致的副本,自然也就没法克隆出一个功能正常的Scanner。另外Scanner自身还有很多内部缓存、分隔符配置等状态,这些也很难被完整复制。

总结一下:重复创建Scanner本身不是问题,但关闭第一个Scanner会把共享的System.in关掉,导致后续所有基于它的Scanner都无法工作;而Scanner的设计从根上就不支持克隆,因为它依赖的资源和自身状态都不具备可复制性。

内容的提问来源于stack exchange,提问作者Paris

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:25:29