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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 15:58:21