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

父类未实现Serializable时如何将其对象类型字段写入序列化文件

问题根因

Java序列化存在既定规则:如果子类实现了Serializable接口,但父类未实现该接口,默认序列化逻辑只会处理子类自身的非transient字段,父类的所有字段都不会参与序列化。你当前已经把父类的基础类型字段拷贝到了子类的speedCopy、productionYearCopy字段中存储,但对于父类的Engine引用类型字段,你在子类中定义的engineCopy加了transient修饰,而transient标记的字段会被默认序列化逻辑直接忽略,同时你也没有在写对象前给engineCopy赋值,所以该字段无法被写入文件。
另外还要注意:如果Engine类本身没有实现Serializable接口,序列化该类型字段时会直接抛出NotSerializableException。

解决方案

方案1:沿用你当前的拷贝字段逻辑,修改对应问题点

  1. 去掉Plane类中engineCopy字段的transient修饰,保证该字段能被默认序列化处理:
class Plane extends Vehicle implements Serializable {                             
    String model;                                                                 
    int flightRange;                                                              
    transient Chassis chassis;                                                    
    int speedCopy;                                                                
    Engine engineCopy; // 移除transient修饰                                                 
    int productionYearCopy;
    // 其余原有构造方法、逻辑保持不变
}
  1. 给Engine类实现Serializable接口:
public class Engine implements Serializable {
    private String type;
    private int power;
    // 原有构造方法、getter/setter等逻辑保持不变
}
  1. 修改写对象前的赋值逻辑,补充engineCopy的赋值:
if (aClass.getSimpleName().equals("Plane")) {                                       
    Plane plane = (Plane) value;                                                    
    plane.speedCopy = plane.speed;
    plane.engineCopy = plane.engine; // 新增赋值逻辑                                                 
    plane.productionYearCopy = plane.productionYear;                                
    objectOutputStream.writeObject(plane);                                          
}
  1. 修改Plane类的readObject方法,反序列化完成后把拷贝字段回写到父类的对应字段中,避免读出来的对象父类字段为默认值:
private void readObject(ObjectInputStream objectInputStream) {                
    try {                                                                     
        objectInputStream.defaultReadObject();                                
        int numberOfWheels = objectInputStream.readInt();                     
        int diameter = objectInputStream.readInt();                           
        String load = (String) objectInputStream.readObject();                
        this.chassis = new Chassis(new Wheel(load, diameter), numberOfWheels);
        // 新增:将拷贝字段回写至父类
        this.speed = this.speedCopy;
        this.engine = this.engineCopy;
        this.productionYear = this.productionYearCopy;                                
    } catch (Exception e) {                                                   
        e.printStackTrace();                                                                        
    }
}

方案2(优化可选):无需额外定义拷贝字段,直接在自定义序列化方法中处理父类字段

你可以直接在writeObject和readObject中手动处理父类字段的序列化和反序列化,省去冗余的拷贝字段定义,也不需要在写对象前手动赋值:

private void writeObject(ObjectOutputStream objectOutputStream) {             
    try {                                                                     
        objectOutputStream.defaultWriteObject();
        // 手动序列化父类字段
        objectOutputStream.writeInt(speed);
        objectOutputStream.writeObject(engine);
        objectOutputStream.writeInt(productionYear);
        // 原有chassis序列化逻辑保持不变
        objectOutputStream.writeInt(chassis.numberOfWheels);                  
        objectOutputStream.writeInt(chassis.wheel.diameter);                  
        objectOutputStream.writeObject(chassis.wheel.load);                   
    } catch (Exception e) {                                                   
        e.printStackTrace();                                                  
    }                                                                         
}

private void readObject(ObjectInputStream objectInputStream) {                
    try {                                                                     
        objectInputStream.defaultReadObject();
        // 手动读取父类字段并赋值
        this.speed = objectInputStream.readInt();
        this.engine = (Engine) objectInputStream.readObject();
        this.productionYear = objectInputStream.readInt();
        // 原有chassis反序列化逻辑保持不变
        int numberOfWheels = objectInputStream.readInt();                     
        int diameter = objectInputStream.readInt();                           
        String load = (String) objectInputStream.readObject();                
        this.chassis = new Chassis(new Wheel(load, diameter), numberOfWheels);                                
    } catch (Exception e) {                                                   
        e.printStackTrace();                                                                        
    }
}

采用该方案可以直接删除Plane类中speedCopy、engineCopy、productionYearCopy三个冗余字段,也不需要在写对象的方法中做拷贝赋值操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 01:45:03