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

Serializable by extending with empty constructor?

TLDR:有没有办法强制 subclass 有一个空的构造函数,而 super 没有?

我需要从序列化的数据容器中初始化不可序列化的 class、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
}

我的第一个想法是将其扩展为可序列化 class。我可以使用它的 ID 属性的可序列化字符串并添加空构造函数,而不是使用 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 没有空构造函数,我在 subclass 的空构造函数中遇到错误。有没有办法在 super 没有时强制 subclass 有一个空的构造函数?

根据The Serializable Interface

A Serializable class must do the following:

  • Implement the java.io.Serializable interface
  • Identify the fields that should be serializable (Use the serialPersistentFields member to explicitly declare them serializable or use the transient keyword to denote nonserializable fields.)
  • Have access to the no-arg constructor of its first nonserializable superclass

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

如果扩展class不是必须的,你可以考虑像下面这样使用封装:

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
}

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