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

Java读取标准输入(非交互式)时出现诡异输入错误问题

排查Java标准输入读取的诡异错误及修复方案

我一眼就看到了几个会导致输入异常的问题,咱们一步步拆解并修复:

问题1:多个Scanner实例共享System.in流

你的代码里Student类和Marks类各自创建了Scanner实例来读取标准输入。当多个Scanner操作同一个System.in时,很容易出现流的状态混乱——比如其中一个Scanner的读取操作会打乱另一个的指针位置,甚至如果某个Scanner被关闭(哪怕是隐式触发的),整个System.in都会被关闭,后续读取直接抛出异常。

问题2:sc.next()无法读取带空格的名字

sc.next()只会读取到第一个空白字符(空格、换行、制表符等)就停止,如果用户输入的名字是Mary Smith这种带空格的,name只会拿到Mary,紧接着的sc.nextInt()会尝试读取Smith,这显然不是整数,直接触发InputMismatchException。


修复后的完整代码

import java.util.Scanner;

class Student {
    private int rollno;
    private String name;
    // 共用一个Scanner实例,避免流冲突
    private Scanner sc;

    // 构造方法传入全局的Scanner
    public Student(Scanner sc) {
        this.sc = sc;
    }

    public void getRollNo() {
        System.out.println("Enter name and roll no (name can include spaces):");
        // 读取包含空格的完整名字
        name = sc.nextLine();
        
        // 校验并读取学号,确保输入是有效整数
        while (!sc.hasNextInt()) {
            System.out.println("请输入有效的整数学号!");
            sc.nextLine(); // 吃掉无效输入内容
        }
        rollno = sc.nextInt();
        sc.nextLine(); // 吃掉nextInt()留下的换行符,避免影响后续读取
    }

    public void putRollNo() {
        System.out.println("Name=" + name);
        System.out.println("Regno=" + rollno);
    }
}

class Marks extends Student {
    protected int mark1, mark2, mark3;

    // 继承父类的Scanner实例
    public Marks(Scanner sc) {
        super(sc);
    }

    public void getMarks() {
        System.out.println("Enter marks for three subjects:");
        // 校验并读取三科成绩
        while (!sc.hasNextInt()) {
            System.out.println("请输入有效的整数成绩!");
            sc.nextLine();
        }
        mark1 = sc.nextInt();
        
        while (!sc.hasNextInt()) {
            System.out.println("请输入有效的整数成绩!");
            sc.nextLine();
        }
        mark2 = sc.nextInt();
        
        while (!sc.hasNextInt()) {
            System.out.println("请输入有效的整数成绩!");
            sc.nextLine();
        }
        mark3 = sc.nextInt();
        sc.nextLine();
    }

    public void putMarks() {
        putRollNo();
        System.out.println("Mark1=" + mark1);
        System.out.println("Mark2=" + mark2);
        System.out.println("Mark3=" + mark3);
    }
}

// 测试入口类
public class StudentTest {
    public static void main(String[] args) {
        // 全局只创建一个Scanner实例,传递给所有需要的类
        Scanner sc = new Scanner(System.in);
        Marks studentMarks = new Marks(sc);
        studentMarks.getRollNo();
        studentMarks.getMarks();
        studentMarks.putMarks();
        sc.close(); // 最后统一关闭Scanner
    }
}

关键修复说明

  • 单一Scanner实例:在main方法中创建唯一的Scanner,通过构造方法传递给Student和Marks类,所有输入操作共用这一个实例,彻底避免流冲突问题。
  • 用nextLine()读取完整名字:可以处理包含空格的姓名输入,同时在nextInt()之后调用sc.nextLine()吃掉残留的换行符,防止下一次nextLine()直接读取空字符串。
  • 输入校验逻辑:增加循环判断确保用户输入的学号和成绩都是有效整数,避免因非法输入导致的程序崩溃。

内容的提问来源于stack exchange,提问作者S4rt-H4K

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:06:01