Java Scanner循环2次录入却额外要求第三行输入问题排查
问题背景
刚加入技术社区首次提问,编写了两个Java类实现学生信息录入打印功能:
Student基础类:定义姓名、姓氏、三门成绩的私有字段,包含全参构造方法、对应字段的getter方法,重写toString方法格式化输出学生成绩信息StudentMain主类:定义静态LinkedList<Student>集合存储学生对象,静态Scanner实例接收控制台输入,包含main入口方法、addStudent学生录入方法、printList列表打印方法三个核心逻辑
故障现象
addStudent方法内for循环设置终止条件为x < 2,预期录入2条学生数据就执行打印逻辑,但实际运行时:
- 输入2条符合格式的学生数据按下回车后,程序不会继续执行,光标停在新一行等待第三次输入
- 必须输入第三行内容再次回车,程序才会执行打印逻辑
- 第三行输入的内容不会被解析、也不会出现在最终输出结果中
复现输入
输入以下两行内容(不含外层引号):
"Young John 9 9 9"
"Johnson Anne 8 8 8"
按下回车后程序等待第三行输入,输入任意内容回车后才输出结果,第三行内容不展示。
原始代码
Student类
public class Student { private String name; private String surname; private int firstMark; private int secondMark; private int finalExamMark; public Student(String name, String surname, int firstMark, int secondMark, int finalExamMark) { this.name = name; this.surname = surname; this.firstMark = firstMark; this.secondMark = secondMark; this.finalExamMark = finalExamMark; } public String getName() { return name; } public String getSurname() { return surname; } public int getFirstMark() { return firstMark; } public int getSecondMark() { return secondMark; } public int getFinalExamMark() { return finalExamMark; } @Override public String toString (){ return this.name + " " + this.surname + " got " + this.firstMark + " at English, " + this.secondMark + " at Math and " + this.finalExamMark + " at the final exam."; } }
StudentMain类
public class StudentMain { static LinkedList<Student> courseAttend = new LinkedList<>(); static Scanner scanner = new Scanner(System.in); public static void main(String[] args) { addStudent(); printList(courseAttend); } private static void addStudent() { for (int x = 0; x < 2; x++) { String s1 = scanner.nextLine(); String[] split = s1.split("\\s"); courseAttend.add(new Student(split[0], split[1], Integer.parseInt(split[2]), Integer.parseInt(split[3]), Integer.parseInt(split[4]))); scanner.nextLine(); // 问题出在这行 } scanner.close(); } private static void printList(LinkedList<Student> lista) { for (Student elem : lista) { System.out.println(elem); } } }
问题根因
addStudent的for循环里,每解析完一行学生数据、添加到集合之后,多写了一次无意义的scanner.nextLine()调用。scanner.nextLine()每次执行都会阻塞等待读取一整行控制台输入,2次循环总共会触发4次nextLine()调用,也就是必须读取满4行输入才会退出循环:
- 第1次
nextLine():读取第一行学生数据,解析为第一个Student对象存入集合 - 第2次
nextLine()(多余的那行):读取第二行学生数据,但是没有做任何解析、存储操作,直接丢弃 - 第3次
nextLine():循环第二次执行时触发,读取第三行输入,解析为第二个Student对象存入集合 - 第4次
nextLine()(第二次循环里多余的那行):读取第四行输入后直接丢弃,循环结束
实际测试时只输入3行就触发打印,大概率是第三行输入后触发了流结束标识、或者第四行读取到空内容直接退出阻塞,才会出现描述的现象。
修复方案
直接删除addStudent方法里,添加完学生对象后的多余scanner.nextLine();语句即可,修复后的addStudent方法代码如下:
private static void addStudent() { for (int x = 0; x < 2; x++) { String s1 = scanner.nextLine(); String[] split = s1.split("\\s"); courseAttend.add(new Student(split[0], split[1], Integer.parseInt(split[2]), Integer.parseInt(split[3]), Integer.parseInt(split[4]))); } scanner.close(); }
补充提示:当前代码没有做输入合法性校验,如果输入内容拆分后字段数不足5、或者成绩位置输入非数字内容,会抛出数组越界、数字格式异常,后续可以增加输入校验逻辑提升程序健壮性。
内容的提问来源于stack exchange,提问作者ruh01
相关产品推荐
相关产品推荐

