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

NoSuchElementException死循环与PMD DD异常相关代码问题求助

问题根因

  • 你代码里最核心的错误是在try-with-resources语法中创建Scanner实例:try-with-resources会在代码块执行结束后自动关闭资源,你关闭Scanner的同时会连带关闭底层的System.in输入流。第一次循环结束后System.in就已经是关闭状态,后续循环再新建Scanner读取已经关闭的流,就会持续抛出NoSuchElementException,进入无限循环。
  • 其次你提到的nextLine()相关问题是第二个常见误区:scanner.nextInt()只会读取输入的数字部分,不会消费数字后面的换行符,缓冲区残留的换行符会被下一次nextLine()直接读取到空内容,导致逻辑异常。

修复方案

方案1:全局复用同一个Scanner实例,不要每次循环新建也不要随便关闭

你可以把Scanner定义为类成员变量,或者在方法外创建后传入,避免反复开闭System.in,同时处理掉nextInt残留的换行符:

public class Console {
    // 全局复用同一个Scanner,不要主动关闭
    private final Scanner scanner = new Scanner(System.in);

    public int readInteger(String prompt) {
        Integer x = null;
        while(x == null) {
            try {
                System.out.print(prompt);
                x = scanner.nextInt();
                // 消费掉数字后面残留的换行符,避免影响后续nextLine调用
                scanner.nextLine();
            } catch(InputMismatchException exc) {
                System.out.println("输入错误,请输入合法整数");
                // 输入不匹配的时候也要把错误的整行输入消费掉,避免无限卡这里
                scanner.nextLine();
            } catch(NoSuchElementException exc) {
                System.out.println("输入流已关闭,无法读取内容");
                // 流已关闭无需继续循环,直接抛出或者返回默认值即可,这里选择抛出终止逻辑
                throw new RuntimeException("输入流已终止", exc);
            }
        }
        return x;
    }
}

方案2:直接统一用nextLine读取整行再转成整数,彻底避免换行残留问题

如果你的场景后续要频繁混用读取整数和字符串,更稳妥的方式是所有输入都按行读取,再做类型转换:

public int readInteger(String prompt) {
    Integer x = null;
    while(x == null) {
        try {
            System.out.print(prompt);
            String input = scanner.nextLine();
            x = Integer.parseInt(input);
        } catch(NumberFormatException exc) {
            System.out.println("输入错误,请输入合法整数");
        } catch(NoSuchElementException exc) {
            System.out.println("输入流已关闭,无法读取内容");
            throw new RuntimeException("输入流已终止", exc);
        }
    }
    return x;
}

注意事项

  • 不要在任何场景下关闭包装了System.in的Scanner,一旦关闭System.in整个程序生命周期内都无法再重新打开读取输入。
  • 所有异常分支都要记得消费掉当前缓冲区的无效内容,否则异常后缓冲区残留的内容会被下一次读取逻辑重复触发异常,导致无限循环。

内容的提问来源于stack exchange,提问作者nighty

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 23:45:07