You need to enable JavaScript to run this app. Java用Scanner为对象属性赋值时抛InvocationTargetException排查
优惠活动
大模型
产品
解决方案
定价
更多

Java用Scanner为对象属性赋值时抛InvocationTargetException排查

Scanner 读取输入时抛出 InvocationTargetException 问题分析

根本原因

  • 代码中setPersonalId()方法的实现存在致命问题:它用try-with-resources语法创建了绑定System.in的Scanner实例
    try (
            Scanner scanner2 = new Scanner(System.in);
    ) {
    
  • try-with-resources机制会在代码块执行完成后自动关闭持有的资源。由于Scanner是对System.in全局输入流的包装类,关闭Scanner对象时,底层关联的System.in输入流会被一并彻底关闭。
  • 等setPersonalId()执行完毕回到SignPerson()方法,无论你后续创建多少个新的Scanner实例去调用nextLine()读取输入,都会因为底层System.in已经处于关闭状态抛出IO异常。
  • 你看到的InvocationTargetException只是一层包装壳:这个异常通常是反射调用场景下,JVM把目标方法内部抛出的原始异常包装后抛出的类型,本身不携带具体错误信息,如果你只盯着外层的异常类型搜索解决方案,自然找不到问题根因——真正的“输入流已关闭”的错误信息,藏在这个异常的cause节点里。
  • 这也是为什么你换其他Scanner实例也会抛异常的原因:System.in是JVM启动时初始化的全局单例输入流,只要被关闭过一次,后续所有绑定它的读取操作都会直接失败——哪怕你换成BufferedReader去读输入也一样报错,和换不换Scanner对象没有关系。

修复方案

  • 全程序范围只维护一个绑定System.in的Scanner实例,不要在局部方法里反复创建、关闭绑定系统输入流的Scanner:
    1. 把Scanner实例提升为类级别的全局成员,整个注册流程共用同一个对象
    2. 删除setPersonalId()里单独创建Scanner的逻辑,直接复用全局的Scanner实例读取pesel输入,同时移除try-with-resources的自动关闭逻辑,避免全局输入流被意外关闭
    3. 排查这类包装异常时,记得打印完整的异常调用链,顺着InvocationTargetException往下找嵌套的原始异常,才能看到真正的报错原因

内容的提问来源于stack exchange,提问作者Jakub Kołacz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.26 03:06:03