通过使用空构造函数扩展可序列化?

时间:2016-07-03 00:13:49

标签: java serializable

TLDR:有没有办法强制子类在超级时没有空构造函数?

我需要从序列化数据容器初始化一个不可序列化的类TravelTimeDataArrayTravelTimeDataArray无法序列化,因为它没有实现Serializable接口,缺少空构造函数,并且使用类型为Link的非序列化字段。

public class TravelTimeDataArray implements TravelTimeData {
    private final double[] timeSum;
    private final int[] timeCnt;
    private final double[] travelTimes;
    private final Link link; //I'm not serializable

    public TravelTimeDataArray(final Link link, final int numSlots) {
        this.timeSum = new double[numSlots];
        this.timeCnt = new int[numSlots];
        this.travelTimes = new double[numSlots];
        this.link = link;
        resetTravelTimes();
    }

//getters and setters
}

我的第一个想法是将其扩展为可序列化的类。我可以使用它的ID属性的可序列化String并添加空构造函数,而不是使用Link

public class SerialTravelTimeDataArray extends TravelTimeDataArray implements java.io.Serializable{
    private final String linkId = null;  // I am serializable
    public SerialTravelTimeDataArray(){ } 

    public SerialTravelTimeDataArray(TravelTimeDataArray  ttDA){
      // intialize me using ttDA's data
    } 

   // Methods to serialize the fields.

   // Methods to populate super's fields from the deserialized data containers
   }

由于super没有空构造函数,因此我得到了子类的空构造函数的错误。有没有办法强制子类在超级不具有空构造函数时?

1 个答案:

答案 0 :(得分:2)

根据The Serializable Interface

  

Serializable类必须执行以下操作:

     
      
  • 实现java.io.Serializable接口
  •   
  • 标识应该可序列化的字段(使用serialPersistentFields成员显式声明它们可序列化   或使用transient关键字表示不可序列化的字段。)
  •   
  • 可以访问其第一个非可序列化超类
  • 的no-arg构造函数   

对象的第一个非可序列化超类的无参数构造函数需要具有访问权限,因为在反序列化对象时将调用它。否则,将抛出异常。请注意,序列化对象不会调用其超类的默认构造函数,也不会抛出任何异常。

如果不必扩展类,可以考虑使用如下的封装:

public class Foo implements Serializable {

    private final double[] timeSum;
    private final int[] timeCnt;
    private final double[] travelTimes;
    private final String linkId;
    private final transient TravelTimeDataArray ttDA;


    public Foo(TravelTimeDataArray ttDA) {
        this.ttDA = ttDA;
        this.timeSum = ttDA.getTimeSum();
        this.timeCnt = ttDA.getTimeCnt();
        this.travelTimes = ttDA.getTravelTimes();
        this.linkId = ttDA.getLink().getId();
    }

    // Methods
}

如果您不需要在班级中访问TravelTimeDataArray,则可以跳过字段transient TravelTimeDataArray ttDA。希望这可以提供帮助。