You need to enable JavaScript to run this app. Java序列化存储对象时FileOutputStream所在try块直接跳转catch块问题
优惠活动
大模型
产品
解决方案
定价
更多

Java序列化存储对象时FileOutputStream所在try块直接跳转catch块问题

问题核心原因

  • filename字段定义和访问错误
    如果你调用save方法的Player对象是从历史存档反序列化得到的,被transient修饰的filename字段不会参与序列化,反序列化后该字段值为null,传入FileOutputStream构造函数时会直接抛出NullPointerException进入catch块。
    如果save方法定义在Player类外部,filename是Player的私有实例字段,外部类无法直接访问,也会触发运行时异常。
    同时filename是固定的存档文件名,完全不需要定义为实例成员,更不需要加transient修饰。
  • 异常信息被屏蔽
    当前catch块只打印了自定义提示,没有输出具体异常栈,无法第一时间定位错误原因。
  • 流资源未安全释放
    当前手动关闭流的写法如果在writeObject阶段抛出异常,流不会正常关闭,可能导致文件句柄泄漏。

修复方案

  1. 调整Player类中filename的定义,改为静态常量:
final class Player implements Serializable{
    private static final long serialVersionUID = 2676858593456923114L;
    // 改为静态常量,不需要序列化也全局有效
    public static final String FILENAME = "BSR.data";
    // 其余原有字段保持不变
    private int hp;
    @SuppressWarnings("rawtypes")
    private ArrayList<ArrayList> inventory = new ArrayList<>();
    private ArrayList<String> myLevelUps = new ArrayList<>();
    private ArrayList<Crystal> myCrystals = new ArrayList<>();
    private ArrayList<Weapon> myWeapons = new ArrayList<>();
    private int myLevel = 0;
    private int myGold;
}
  1. 重构save方法,使用try-with-resources自动管理流资源,添加异常栈打印:
void save(Player player) {
    try (FileOutputStream out = new FileOutputStream(Player.FILENAME);
         ObjectOutputStream objectOut = new ObjectOutputStream(out)) {
        objectOut.writeObject(player);
        System.out.println("你的游戏已存档到" + Player.FILENAME);
    } catch (Exception e) {
        System.err.println("无法创建游戏存档数据");
        // 打印异常栈定位具体问题
        e.printStackTrace();
    }
}

额外注意项

请确认inventory字段中存储的嵌套ArrayList的元素类型实现了Serializable接口,泛型擦除后如果元素不可序列化,写入对象时也会抛出NotSerializableException。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.20 19:27:01