Java 不可序列化父类的可序列化子类

Java 不可序列化父类的可序列化子类,java,android,serialization,Java,Android,Serialization,我正在用android/java中Location子类的序列化来解决一个难题 位置不可序列化。 我有一个名为FALocation的第一个子类,它没有任何实例变量。我已经声明它是可序列化的 然后我有一个叫做Waypoint的第二个类,看起来像这样: public class Waypoint extends FALocation implements Serializable { /** * */ private static final long seri

我正在用android/java中Location子类的序列化来解决一个难题

位置不可序列化。 我有一个名为FALocation的第一个子类,它没有任何实例变量。我已经声明它是可序列化的

然后我有一个叫做Waypoint的第二个类,看起来像这样:

public class Waypoint extends FALocation implements Serializable {

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

    /* Class variables *******************************************************/
    private static int CLASS_VERSION=1; //Used to version parcels

    /* Instance variables ****************************************************/
    private transient String type=DataHelper.PT_TYPE_US;
    private transient String country; 
    private transient String name=null;
    private transient String description=null;
    private transient int elevation = 0;
    private transient int population = 0; // Afterthought, added to match the DB structure

    /* Constructors **********************************************************/    
    public Waypoint() {
        super();
    }

    public Waypoint(double lat, double lon, String name, String description) {
        super(lat, lon);
        this.setName(name);
        this.setDescription(description);
    }

    public Waypoint(Location l) {
        super(l);
    }

    public Waypoint(String provider) {
        super(provider);
    }


    /* Implementing serializable */
    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
        Log.v("DroidFA", "Serialising \"%s\" (v%d).", Waypoint.class.getSimpleName(), CLASS_VERSION);
        out.writeInt(CLASS_VERSION);

        out.writeObject(type);
        out.writeObject(country);
        out.writeObject(name);
        out.writeObject(description);
        out.writeInt(elevation);
        out.writeInt(population);
    }

    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {

        int serialClassVersion = in.readInt();
        Log.v("DroidFA", "Deserialising \"%s\" (v%d).", Waypoint.class.getSimpleName(),serialClassVersion);

        type = (String) in.readObject();
        country = (String) in.readObject();
        name = (String) in.readObject();
        description = (String) in.readObject();
        elevation = in.readInt();
        population = in.readInt();
    }
}
序列化工作正常

反序列化产生以下异常(航段对象包含一个航路点):


看起来位置没有公共/受保护的无参数构造函数。为了使它在子类中可用于序列化,需要这样一个构造函数

说:

要允许序列化不可序列化类的子类型,请 子类型可能负责保存和恢复状态 超类型的公共、受保护和(如果可访问)包的 领域。只有当类 它有一个可访问的无参数构造函数来初始化 阶级的状态。如果出现以下情况,则声明类可序列化是错误的 事实并非如此。错误将在运行时检测到

与序列化规范中的词语相同:

可序列化类必须执行以下操作:。。。访问 它的第一个非序列化超类没有参数构造函数

这可以解释为什么只有在反序列化中才会出现问题,因为在序列化过程中,构造函数自然不会被调用

在没有可访问构造函数的情况下失败的小示例:

public class A {
    public A(String some) {};
    private A() {} //as protected or public everything would work
}

public class B extends A implements Serializable {
    public B() {
        super("");
    }
    //these doesn't really matter
    //private void writeObject(java.io.ObjectOutputStream out) throws IOException {  }
    //private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { }
}

public class BSerializer {

    public static void main(String ... args) throws Exception {
        B b = new B();

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(b);
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        B deserialized = (B) ois.readObject();   //InvalidClassException
    }
}

是否绝对有必要序列化该位置?也许您可以将其标记为瞬态,并在反序列化对象后动态获取它。():

Q:如果类A没有实现Serializable,但是子类B实现Serializable,那么当B被序列化时,类A的字段会被序列化吗

答:只有可序列化对象的字段才会被写入和恢复。仅当对象具有将初始化不可序列化超类型字段的无参数构造函数时,才可以还原该对象。如果子类可以访问超类的状态,它可以实现writeObject和readObject来保存和恢复该状态


因此,如果子类可以访问其不可序列化超类的字段,则可以使用writeObject和readObject协议来实现序列化。否则,将有无法序列化的字段。

看来,问题出在其他地方。Leg.java:262)Leg行262是:“from=(航路点)in.readObject();”这就是问题所在;)。我需要将
位置
与它的大多数成员一起保存,而不仅仅是纬度和经度。我最终编写了自己的
Serializable
类。请看我的答案:android.location.location;当程序试图访问无法从引用位置访问的字段或方法时,会引发IllegalAccessException。位置确实没有无参数公共构造函数。但是我应该从哪里开始呢?不幸的是,您不能直接序列化它。除了将状态保存到其他地方、获取保存的状态并构造新位置(或任何扩展位置)之外,您不能做任何事情。@bugs_u确实如此,但这与此案例无关。没有引发IllegalAccessException,“IllegalAccessException”是InvalidClassException的构造函数的msg参数,该构造函数是从ObjectInputStream类中的resolveConstructorClass创建并引发的。好的,我可以从子类序列化位置字段,但问题是它无论如何都会尝试反序列化位置。我可以从子类中阻止这种情况发生吗?好的,我已经从封闭对象中“伪”序列化了我的Location子类。解决了这个问题。谢谢。”我已经从封闭的对象中“伪”系列化了我的位置子类。“嗨,我面对的是相同的,你能详细说明一下吗?”。伪在这里是什么意思?
public class A {
    public A(String some) {};
    private A() {} //as protected or public everything would work
}

public class B extends A implements Serializable {
    public B() {
        super("");
    }
    //these doesn't really matter
    //private void writeObject(java.io.ObjectOutputStream out) throws IOException {  }
    //private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { }
}

public class BSerializer {

    public static void main(String ... args) throws Exception {
        B b = new B();

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(b);
        ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
        ObjectInputStream ois = new ObjectInputStream(bais);
        B deserialized = (B) ois.readObject();   //InvalidClassException
    }
}