Java Scanner抛出NoSuchElementException: no line found问题求助
Scanner.nextLine()抛出NoSuchElementException问题排查与解决
问题概述
开发问答游戏时,调用Scanner.nextLine()触发java.util.NoSuchElementException: no line found错误,错误栈如下:
Exception in thread "main" java.util.NoSuchElementException: no line found at java.base/java.util.Scanner.nextLine(Scanner.java:1651) at Player.setUsername(Player.java:33) at Quiz.printPlayerEditor(Quiz.java:118) at Run.main(Run.java:20)
相关代码片段:
Player.java 报错的setUsername方法
public void setUsername(Scanner in) { String user = ""; do { while (!in.hasNextLine() && !user.isEmpty() && user.length() < 16 ) { Quiz.printError(); in.next(); } user = in.nextLine(); //Line 33 username = user; Quiz.setProperties("playerusername", username); }while(!username.equals(user)); }
Quiz.java 调用setUsername的printPlayerEditor方法
public void printPlayerEditor(Scanner in) { System.out.println("<> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <>"); System.out.println("Welcome to the Player editor:"); System.out.println("Your current username is | " + player.getUsername() + " |"); System.out.println("Please enter a new username between 1-16 characters:"); System.out.println("<> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <> <>"); player.setUsername(in); System.out.println("Your username is now | " + player.getUsername() + " |\n"); }
Run.java 主方法调用逻辑
import java.util.Scanner; public class Run { public static void main(String[] args) { Quiz quiz = new Quiz(); Player player = new Player(); quiz.setPlayer(player); quiz.populateQuestions(); int input = quiz.printMenu1(); Scanner in = new Scanner(System.in); switch (input) { case 1: if (Quiz.getProperties("playerusername").isEmpty()) { quiz.printPlayerCreator(in); input = 2; } else { quiz.printPlayerEditor(in); input = 2; } case 2: try { quiz.printUnitMenu(in); } catch (NullPointerException e) { quiz.printPlayerCreator(in); } break; default: Quiz.printError(); quiz.printMenu1(); break; } in.close(); } }
问题原因与修复方案
1. 输入流被提前关闭
检查quiz.printMenu1()方法,如果该方法内部创建了独立Scanner并调用close(),会直接关闭底层System.in输入流,导致后续创建的Scanner实例无法读取输入,抛出异常。
修复:
整个程序只维护一个Scanner实例,仅在程序结束时关闭。修改printMenu1()方法,改为传入main中创建的Scanner,禁止在该方法内调用close()。
2. setUsername方法逻辑错误
原方法中while (!in.hasNextLine() && !user.isEmpty() && user.length() < 16 )条件逻辑混乱:
!in.hasNextLine()表示无输入行可用,此时调用in.next()会加剧异常风险- 条件无法实现用户名长度验证的需求
修复后的setUsername方法:
public void setUsername(Scanner in) { String user; do { // 先校验输入流状态 while (!in.hasNextLine()) { Quiz.printError(); if (in.isClosed()) { return; } } user = in.nextLine().trim(); // 验证用户名长度 if (user.isEmpty() || user.length() > 16) { Quiz.printError(); } else { username = user; Quiz.setProperties("playerusername", username); break; } } while (true); }
3. switch语句case穿透问题
Run.java中case 1未添加break,会直接执行case 2的代码。若printPlayerEditor/printPlayerCreator内部操作导致Scanner失效,会引发后续异常。
修复:
在case 1末尾添加break:
case 1: if (Quiz.getProperties("playerusername").isEmpty()) { quiz.printPlayerCreator(in); input = 2; } else { quiz.printPlayerEditor(in); input = 2; } break; // 添加该break避免穿透 case 2: try { quiz.printUnitMenu(in); } catch (NullPointerException e) { quiz.printPlayerCreator(in); } break;
4. 禁止在非main方法中关闭Scanner
检查printPlayerCreator、printUnitMenu等所有接收Scanner的方法,确保它们不会调用in.close(),仅在main方法最后统一关闭Scanner。
内容的提问来源于stack exchange,提问作者Sharky
相关产品推荐
相关产品推荐

