如何避免java.util.Scanner读取System.in时抛出NoSuchElementException
问题根因
你的猜测符合实际情况,问题由之前其他方法中关闭Scanner的操作触发:
- 包装
System.in的Scanner执行close()方法时,会同时关闭底层的System.in全局输入流 System.in是JVM全局唯一的标准输入流,一旦关闭就无法重新打开,后续新建的Scanner尝试从已关闭的System.in读取数据时,会直接判定到达输入流末尾,不等用户输入就抛出NoSuchElementException
修复方案
- 全局复用单个
System.in包装的Scanner实例,不要每次读取输入都新建Scanner。可以将Scanner定义为类的静态全局成员,全程不主动关闭,程序退出时JVM会自动回收资源 - 删除所有针对包装
System.in的Scanner的close()调用,避免误关全局输入流 - 补充异常捕获逻辑:当前仅捕获
InputMismatchException,可追加捕获NoSuchElementException、IllegalStateException处理输入流异常场景 - 处理输入不匹配时记得调用
nextLine()清空输入缓冲区残留的错误内容,避免后续读取直接拿到无效值
调整后代码示例
// 全局复用的Scanner,仅初始化一次 private static final Scanner GLOBAL_USER_INPUT = new Scanner(System.in); public static double collectDepositAmount(int accountNum){ System.out.print("Enter how much you would like to deposit in Account #" + accountNum + ": $"); double finalDeposit; try{ double inputDeposit = GLOBAL_USER_INPUT.nextDouble(); // 你的原有业务逻辑 finalDeposit = inputDeposit; } catch (InputMismatchException e) { // 清空错误输入缓存 GLOBAL_USER_INPUT.nextLine(); // 你的原有输入不匹配处理逻辑 throw new RuntimeException("输入金额格式错误"); } catch (NoSuchElementException | IllegalStateException e) { // 输入流不可用的兜底处理 throw new RuntimeException("输入读取失败,请重启程序"); } return finalDeposit; }
内容的提问来源于stack exchange,提问作者Irish Jet
相关产品推荐
相关产品推荐

