Java项目中打开并关闭两个不同Scanner的问题排查
问题分析与解决方案
首先我先把你给出的代码补全(看起来是输入到一半截断了),方便更清晰地理解场景:
package scannerDebug; import java.util.Scanner; public class Class1 { private String name_; public Class1(String name) { name_ = name; } public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.print("Enter name: "); String inputName = in.nextLine(); Class1 obj = new Class1(inputName); // 如果执行这行,后续再用Scanner读取System.in就会报错 in.close(); } }
问题根源
你碰到的是个非常典型的Scanner使用误区:当你关闭和System.in绑定的Scanner时,它会顺带把底层的System.in输入流也一起关闭。而System.in是JVM进程级别的全局资源,一旦关闭就没法重新打开,这就导致后续任何尝试读取System.in的代码都会抛出异常。
修改变量名没用,因为问题核心根本不是变量名,而是System.in流被提前关闭了。
解决方案
针对这个场景,有两个实用的处理方式:
- 不要手动关闭和
System.in关联的Scanner:System.in由JVM负责管理,当JVM退出时会自动释放这个资源,完全不需要我们手动调用close()。这是最简单直接的解决办法,也是官方推荐的做法。 - 使用全局单例Scanner:如果你的项目需要在多个类、多个方法中读取控制台输入,建议创建一个全局的Scanner实例,整个应用生命周期内复用它,避免重复创建和关闭操作。示例代码如下:
package scannerDebug; import java.util.Scanner; public class ScannerSingleton { private static final Scanner INSTANCE = new Scanner(System.in); private ScannerSingleton() {} // 私有构造,禁止外部实例化 public static Scanner getInstance() { return INSTANCE; } } // 其他类中调用示例 public class Class1 { private String name_; public Class1(String name) { name_ = name; } public static void main(String[] args) { Scanner in = ScannerSingleton.getInstance(); System.out.print("Enter name: "); String inputName = in.nextLine(); Class1 obj = new Class1(inputName); // 全程不需要关闭,整个应用共用这一个实例 } }
这样既避免了关闭流导致的异常问题,也保证了资源的合理复用。
内容的提问来源于stack exchange,提问作者Kiley Campbell
相关产品推荐
相关产品推荐

