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

Java程序异常捕获跳转、递归定位及Scanner关闭问题求助

Java学生成绩簿(HS Edition)问题修复

现存问题

  • scannerGettingStarted方法捕获异常时,会触发runProgram方法的异常捕获逻辑
  • 无法定位递归来源(注:原代码无显式递归,问题由Scanner关闭后异常传播导致流程混乱)
  • 运行时抛出java.lang.IllegalStateException: Scanner closed异常
  • 输入错误后无法回到对应输入步骤(如年级输入错误后无法回到初始输入环节)

核心问题分析

  1. Scanner自动关闭:scannerGettingStarted中使用try-with-resources包裹传入的Scanner,该语法会在代码块结束后自动关闭Scanner。而此Scanner由runProgram创建并传入,关闭后runProgram后续操作会触发非法状态异常。
  2. 异常传播:Scanner关闭后,scannerGettingStarted循环内的下一次输入操作会抛出未捕获异常,传播至runProgram的异常捕获块,导致错误提示混乱。
  3. 输入验证逻辑缺陷:使用schoolname == null判断空值无效(scanner.next()不会返回null),且未针对非整数输入做前置判断,导致异常频繁触发。
  4. 重复关闭Scanner:runProgram在循环结束后会执行input.close(),若此前case2已关闭Scanner,会引发重复关闭问题。

修复方案

  1. 移除scannerGettingStarted中的try-with-resources,避免关闭上层传入的Scanner。
  2. 前置输入验证:针对整数输入(年级、菜单选择),先判断输入是否为整数,避免触发InputMismatchException。
  3. 修正空值判断逻辑:使用isBlank()替代== null,准确检测空字符串。
  4. 调整Scanner关闭时机:仅在用户选择退出时关闭一次,避免重复关闭。
  5. 优化错误处理:清空输入缓冲区的无效内容,确保错误后能回到正确输入步骤。

修复后代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 00:27:16