调用 Scanner.close() 会关闭其底层输入流并释放资源,但若包装 System.in 则永久禁用标准输入;应仅对文件等独占流关闭,System.in 通常不关闭,推荐用 try-with-resources 确保安全释放。
调用 scanner.close() 会关闭其底层的输入流(如 system.in、文件流等),从而释放相关系统资源(如文件句柄、缓冲区内存等)。但关键在于:如果 scanner 包装的是共享流(比如 system.in),关闭 scanner 就等于关闭了该流本身,后续再用它会抛出 illegalstateexception。
Scanner.close() 实际做了什么
Scanner 本身不直接管理操作系统级资源,而是委托给它包装的底层 Readable 或 InputStream/Reader。调用 close() 时:
- 若底层是可关闭的流(如
FileInputStream、BufferedReader),则调用其close()方法; - 若底层是不可关闭的对象(如字符串、数组),则什么也不做;
- 若底层是
System.in,则调用System.in.close()—— 这会永久关闭标准输入流,无法恢复。
流关闭顺序与嵌套包装关系
Java 中流常层层包装(例如 FileInputStream → BufferedInputStream → Scanner)。关闭顺序应从最外层开始,且只需关闭最外层即可(前提是各层实现规范):
- 标准库中的包装流(如
BufferedInputStream、Scanner)在close()时会自动调用被包装流的close(); - 因此,只调用
Scanner.close()即可安全释放整个链路资源; - 但不要手动再去调用底层流的
close(),否则可能重复关闭或引发异常。
何时该关闭 Scanner?常见误区
是否关闭 Scanner 取决于它包装的流来源:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
-
必须关闭:包装的是文件流(
new Scanner(new FileInputStream("a.txt")))、网络流、内存流等独占性资源; -
通常不关闭:包装的是
System.in,因为它是 JVM 启动时创建的全局资源,关闭后其他代码无法再读取控制台输入; - 谨慎关闭:包装的是别人传入的流(如方法参数),应由流的创建者负责关闭,Scanner 使用者不应擅自关闭。
推荐做法:使用 try-with-resources 确保关闭
对于需要关闭的 Scanner(如读文件),优先用 try-with-resources,它会在作用域结束时自动调用 close(),即使发生异常也不会遗漏:
立即学习“Java免费学习笔记(深入)”;
try (Scanner sc = new Scanner(new FileInputStream("data.txt"))) {
while (sc.hasNextLine()) {
System.out.println(sc.nextLine());
}
} // 自动调用 sc.close(),进而关闭 FileInputStream
注意:这个写法仅适用于底层流允许关闭的场景。若误用于 System.in,会导致后续输入失效。


















