首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不可序列化父类的可序列化子类

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

Stack Overflow用户
提问于 2011-10-05 22:06:30
回答 2查看 12.9K关注 0票数 10

我遇到了在android/java中序列化Location子类的问题

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

然后我有一个名为Waypoint的第二个类,如下所示:

代码语言:javascript
复制
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();
    }
}

序列化工作得很好。

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

代码语言:javascript
复制
10-05 13:50:35.259: WARN/System.err(7867): java.io.InvalidClassException: android.location.Location; IllegalAccessException
10-05 13:50:35.267: WARN/System.err(7867):     at java.io.ObjectInputStream.resolveConstructorClass(ObjectInputStream.java:2010)
10-05 13:50:35.267: WARN/System.err(7867):     at java.io.ObjectInputStream.readNewObject(ObjectInputStream.java:2095)
10-05 13:50:35.267: WARN/System.err(7867):     at java.io.ObjectInputStream.readNonPrimitiveContent(ObjectInputStream.java:929)
10-05 13:50:35.267: WARN/System.err(7867):     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2285)
10-05 13:50:35.278: WARN/System.err(7867):     at java.io.ObjectInputStream.readObject(ObjectInputStream.java:2240)
10-05 13:50:35.278: WARN/System.err(7867):     at com.droidfa.navigation.Leg.readObject(Leg.java:262)
.../...
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-10-05 23:15:00

是否一定要序列化位置?也许您可以将其标记为瞬态,并在反序列化对象后动态获取它。(Anyway, from the documentation ):

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

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

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

票数 11
EN

Stack Overflow用户

发布于 2011-10-05 22:22:54

看起来Location没有公共的/受保护的无参数构造函数。这样的构造函数是为了使其可用于子类中的序列化。

http://download.oracle.com/javase/6/docs/api/java/io/Serializable.html说:

为了允许非序列化类的子类型被序列化,该子类型可以承担保存和恢复超类型的公共、受保护和(如果可访问)包字段的状态的责任。只有当它扩展的类具有可访问的无参数构造函数来初始化类的状态时,子类型才可以承担这一责任。如果不是这样,那么声明一个类Serializable是错误的。错误将在运行时被检测到。

并与序列化规范中的文字相同:

可序列化类必须执行以下操作:...可以访问其第一个不可序列化超类的no-arg构造函数

这就解释了为什么只有在反序列化时才会有问题,因为在序列化过程中自然不会调用构造函数。

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

代码语言:javascript
复制
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
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7662579

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档