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

Java关闭Scanner触发NoSuchElementException及内存泄漏问题求解

Java多类循环调用Scanner输入关闭报错问题解决方案

问题根因

  • 当你调用Scanner.close()方法时,该操作不仅会回收Scanner实例本身,还会同步关闭其绑定的底层输入流,你这里绑定的是全局的System.in标准输入流,一旦关闭后整个JVM进程生命周期内都无法再次打开,后续再新建Scanner读取输入就会抛出java.util.NoSuchElementException: No line found异常。
  • 你担心的内存泄漏问题完全不需要顾虑:方法内创建的Scanner是局部变量,方法执行完成后就会被JVM垃圾回收器自动回收,不会长期占用内存;而System.in是JVM内置全局流,程序退出时会自动释放,不存在泄漏风险。

最优优化方案

建议全局复用同一个Scanner实例,避免重复创建对象,也避免流关闭冲突,修改逻辑如下:

  1. 在抽象父类Employee中定义静态全局Scanner,所有子类共用:
import java.util.Scanner;

abstract public class Employee{
    // 全局共用的Scanner实例,整个程序生命周期只创建一次
    public static final Scanner SCAN = new Scanner(System.in);

    public Employee(){}
    String name, surname, rank;
    int salary = 0, daysoff = 20;

    public Employee(String name, String surname, String rank, int salary, int daysoff){
        this.name = name;
        this.surname = surname;
        this.salary = salary;
        this.rank = rank;
        this.daysoff= daysoff;
    }

    // 程序所有输入逻辑执行完成后,调用该方法关闭流
    public static void closeScan(){
        SCAN.close();
    }
}
  1. 所有子类的input_variables方法直接使用父类的静态Scanner,不需要重复创建:
// 以Guard类为例,ITPersonal类同理修改
public void input_variables(){
    System.out.println("First name: ");
    this.name = Employee.SCAN.nextLine();
    System.out.println("Last name: ");
    this.surname = Employee.SCAN.nextLine();
    System.out.println("Night shifts (per month): ");
    this.night_shifts = Employee.SCAN.nextInt();
    System.out.println("Late shifts (per month): ");
    this.late_shifts = Employee.SCAN.nextInt();
    System.out.println("Early shifts (per month): ");
    this.early_shifts = Employee.SCAN.nextInt();
    // nextInt()会残留换行符,要消费掉避免后续nextLine读空
    Employee.SCAN.nextLine();
    System.out.printf("Added %s, %s to company!", this.surname, this.name);
}
  1. main方法所有输入逻辑执行完成后,再统一关闭Scanner:
public static void main(String args[]){
    Employee new_guard[] = new Guard[5];
    Employee new_it[] = new ITPersonal[5];
    Employee new_manager[] = new Management[5];
    int count_guard = 0, count_it = 0, count_manager = 0;

    for(int i = 0; i <= 14; i++){
        if(i % 3 == 0){
            new_guard[count_guard] = new Guard();
            new_guard[count_guard].input_variables();
            count_guard++;
            System.out.println();
        }else if(i % 2 == 0){
            new_it[count_it] = new ITPersonal();
            new_it[count_it].input_variables();
            count_it++;
            System.out.println();
        }else{
            new_manager[count_manager] = new Management();
            new_manager[count_manager].input_variables();
            count_manager++;
            System.out.println();
        }
    }
    // 所有输入完成后统一关闭流
    Employee.closeScan();

    int k = 0, j = 0, l = 0;
    for(int i = 0; i < 15; i++){
        if(i % 3 == 0){
            System.out.println(new_manager[k].toString());
                k++;
            }else if(i % 2 == 0){
                System.out.println(new_it[j].toString());
                j++;
            }else{
                System.out.println(new_guard[l].toString());
                l++;
            }
        }
    }

其他代码问题修正

  • 字符串相等判断不要用==,要用equals()方法,比如if("Senior Developer".equals(this.rank)),否则会出现判断失效的问题
  • 注意变量名拼写统一:你的代码里同时出现了rang和rank、bonusdays和bonusDays、bonusTage等拼写不一致的问题,会导致编译报错
  • 调用nextInt()后必须手动消费残留的换行符,否则下一次调用nextLine()会直接读取到空字符串,出现输入错位的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 20:54:04