今天工作时发现一个序列化的问题:
基类(类A)没有实现序列化接口(Serializable),而子类(类B)实现了序列化接口,对子类对像进行序列化,然后反序列化,这里发现反序化后的对象在基类的中的很多属性都变成了null.
- public abstract class FirstLevel {//基类
- private Map map;
- public FirstLevel(){
- System.out.println("first");
- }
- protected void init(){
- map = new HashMap(0);
- }
- public Map getMap() {
- return map;
- }
- public void setMap(Map map) {
- this.map = map;
- }
- }
- public class SecondLevel extends FirstLevel implements Serializable{
- public SecondLevel(){
- init();
- System.out.println("second");
- }
- }
- public class Test {
- public static void main(String args[]) throws FileNotFoundException, IOException, ClassNotFoundException{
- System.out.println("before:");
- SecondLevel before = new SecondLevel();
- HashMap a = new HashMap();
- a.put("key", "guojje");
- before.setMap(a);
- ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("c:\\t.txt"));
- oos.writeObject(before);
- oos.close();
- System.out.println("after:");
- ObjectInputStream ois = new ObjectInputStream(new FileInputStream("c:\\t.txt"));
- SecondLevel after = (SecondLevel)ois.readObject();
- ois.close();
- System.out.println(after.getMap());
- }
- }
输出:
before:
first
second
after:
first
null
这里map属性我是赋过值的,为什么变成NULL了吗,另外创建对像时调用FirstLevel ,
SecondLevel 两个构造函数,但是反序列化时也调用了FirstLevel的构造函数(理论上序列化是不用调用构造函数的)。
看来没有实现序列化接口的基类并没有真正的序列化与反序列化,而是借用其构造函数来实现对象的初始化(可以肯定得不到序列化时的属性值),因为FirstLevel的构造函数并没有初始化MAP成员,所以返回NULL。
查阅一些资料,JDK文档上这么说:
序列化操作不会写出没有实现 java.io.Serializable 接口的任何对象的字段。不可序列化的 Object 的子类可以是可序列化的。在此情况下,不可序列化的类必须有一个无参数构造方法,以便允许初始化其字段。在此情况下,子类负责保存和还原不可序列化的类的状态。
果然如此。
又一个问题(A>B表示B继承于A):
A > B (Serializable)> C > D(Serializable) > E
反序列化E对象,会调用哪几个构造函数呢,答案是一个, A的. 因为其他类都从基类继承了Serializable接口,而A没有.
下一个问题,如果想完全的序列化E对象怎么办:
在子类中(B,C,D,E都可)来序例化A类的成员,然后赋值上去,别无他法.
转载于:https://blog.51cto.com/guojuanjun/589348