Java程序异常捕获跳转、递归定位及Scanner关闭问题求助
Java学生成绩簿(HS Edition)问题修复
现存问题
scannerGettingStarted方法捕获异常时,会触发runProgram方法的异常捕获逻辑- 无法定位递归来源(注:原代码无显式递归,问题由Scanner关闭后异常传播导致流程混乱)
- 运行时抛出
java.lang.IllegalStateException: Scanner closed异常 - 输入错误后无法回到对应输入步骤(如年级输入错误后无法回到初始输入环节)
核心问题分析
- Scanner自动关闭:
scannerGettingStarted中使用try-with-resources包裹传入的Scanner,该语法会在代码块结束后自动关闭Scanner。而此Scanner由runProgram创建并传入,关闭后runProgram后续操作会触发非法状态异常。 - 异常传播:Scanner关闭后,
scannerGettingStarted循环内的下一次输入操作会抛出未捕获异常,传播至runProgram的异常捕获块,导致错误提示混乱。 - 输入验证逻辑缺陷:使用
schoolname == null判断空值无效(scanner.next()不会返回null),且未针对非整数输入做前置判断,导致异常频繁触发。 - 重复关闭Scanner:
runProgram在循环结束后会执行input.close(),若此前case2已关闭Scanner,会引发重复关闭问题。
修复方案
- 移除
scannerGettingStarted中的try-with-resources,避免关闭上层传入的Scanner。 - 前置输入验证:针对整数输入(年级、菜单选择),先判断输入是否为整数,避免触发
InputMismatchException。 - 修正空值判断逻辑:使用
isBlank()替代== null,准确检测空字符串。 - 调整Scanner关闭时机:仅在用户选择退出时关闭一次,避免重复关闭。
- 优化错误处理:清空输入缓冲区的无效内容,确保错误后能回到正确输入步骤。
修复后代码
private void scannerRecordBook(Scanner scanner){ System.out.println(); System.out.println("[ Method Success ]"); System.out.println("School: " + schoolname); System.out.println("Grade Level: " + gradeLevel); System.out.println("Section: " + section); } private void scannerGettingStarted(Scanner scanner){ System.out.println("\n[ Getting Started ]\n"); while(loop2){ try{ System.out.print("School Name: "); schoolname = scanner.next().trim(); System.out.print("Grade Level: "); // 前置验证:确保输入为整数 while(!scanner.hasNextInt()){ System.out.println("\n+-------------------------+\n 请输入有效的数字\n+-------------------------+"); scanner.nextLine(); // 清空无效输入 System.out.print("Grade Level: "); } gradeLevel = scanner.nextInt(); System.out.print("Section: "); section = scanner.next().trim(); if(schoolname.isBlank() || section.isBlank()){ System.out.println("\n+-------------------------+\n 字段不能为空\n+-------------------------+"); } else if(gradeLevel <= 0){ System.out.println("\n+-------------------------+\n 年级不能为0或负数\n+-------------------------+"); }else{ loop2 = false; scannerRecordBook(scanner); } }catch(Exception e){ System.out.println("\n+--------------------------------+\n 发生错误!输入格式不匹配\n+--------------------------------+\n"); scanner.nextLine(); // 清空缓冲区的无效输入 } } } private void runProgram(){ input = new Scanner(System.in); System.out.println(""" [ Student Gradebook ] "HS Edition" [1] Start [2] Exit """); while(loop){ try{ System.out.print("Number: "); // 前置验证菜单输入为整数 while(!input.hasNextInt()){ System.out.println("\n+--------------------------------+\n 输入不在选项范围内\n+--------------------------------+"); input.nextLine(); System.out.print("Number: "); } choiceOfUser = input.nextInt(); switch(choiceOfUser){ case 1 : loop = false; scannerGettingStarted(input); break; case 2 : System.out.println("+---------------------------+"); System.out.println("-- 退出程序成功 --"); System.out.println("+---------------------------+"); input.close(); loop = false; break; default: System.out.println("\n+--------------------------------+\n 输入不在选项范围内\n+--------------------------------+"); } }catch(Exception error){ System.out.println("\n+--------------------------------+\n 发生错误!输入不在选项范围内\n+--------------------------------+"); input.nextLine(); } } // 仅当Scanner未关闭时执行关闭 if(input != null && !input.isClosed()){ input.close(); } } public Main(){ runProgram(); } public static void main(String[] args) { new Main(); }
修复后效果
- 输入错误后会回到对应输入步骤(如年级输入非数字时,提示错误并重新要求输入年级)
- 不会再触发
runProgram的异常捕获逻辑,错误提示精准对应当前输入环节 - 解决
Scanner closed异常问题 - 输入验证更严谨,空值、无效数字的判断更准确
内容的提问来源于stack exchange,提问作者CarlKilla
相关产品推荐
相关产品推荐

