Java的。是#Serial; Serializable"的孩子?父是自动"可序列化"

时间:2014-09-04 13:08:27

标签: java serialization theory

我想询问实现“Serializable”接口的父节点的子节点是否也实现了“Serializable”接口,或者换句话说,该子节点是否可以被序列化?

5 个答案:

答案 0 :(得分:17)

  

我想询问实现“Serializable”接口的父节点的子节点是否也实现了“Serializable”接口,或者换句话说,该子节点是否可以被序列化?

第一部分的答案是肯定的。这是Java继承的自然结果。

第二部分的答案是并非总是如此!

考虑一下:

public class Parent implements Serializable {
    private int i;
    // ...
}

public class Child extends Parent {
    private final Thread t = new Thread();   // a non-serializable object
    // ...
}

Parent的实例可以序列化,但Child的实例不能......因为它有一个类型(Thread)不可序列化的属性。

(现在,如果t被声明为transient,或者使用默认序列化机制避免ChildChild可以序列化。但我的观点是可序列化是紧急财产,而不是可继承财产。)

答案 1 :(得分:8)

是。如果父实现Serializable,那么任何子类也都是Serializable

static class A implements Serializable {
}

static class B extends A {
}

public static void main(String[] args) {
    Serializable b = new B(); // <-- this is a legal statement. 
}

B也实现了Serializable

答案 2 :(得分:1)

简答:是的,如果父序列化,则子类自动序列化。

长答案:

  1. 如果Parent类是Serializable,那么子类默认为Serializable。 JVM检查父类是否实现Serializable,如果是,则将子类视为可序列化。因此,序列化是一个可继承的概念,从父母到孩子。

    public class ParentSerializableNotChild {

        public static void main(String[] args) throws Exception{
            Child chileSerialize = new Child();
            //Serialization
            FileOutputStream fos = new FileOutputStream("test.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(chileSerialize);
            FileInputStream fis = new FileInputStream("test.ser");
            ObjectInputStream ois = new ObjectInputStream(fis);
            Child childDeserialize = (Child) ois.readObject();
            System.out.println(childDeserialize.i + "---" + childDeserialize.j); //10---20      
        }
    }
    
    class Parent implements Serializable{
        int i = 10;
    }
    
    class Child extends Parent{
        int j = 20;
    }
    
  2. 如果父类不可序列化,那么也可以序列化子类。最好的例子是Object类,Object类不实现Serializable,但任何Object类的子类都可以实现Serializable。

    public class ChildSerializedParentNot {

        public static void main(String[] args) throws Exception{
            Dogy d = new Dogy();
            d.i = 888;
            d.j = 999;      
            FileOutputStream fos = new FileOutputStream("inheritance.ser");
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            System.out.println("Serializing");
            oos.writeObject(d);
            FileInputStream fis = new FileInputStream("inheritance.ser");
            ObjectInputStream ois = new ObjectInputStream(fis);
            System.out.println("Deserializing");
            Dogy d2 = (Dogy) ois.readObject();
            System.out.println(d2.i + "-----" + d2.j);
        }
    }
    class Animal{
        int i = 10;
        Animal(){
            System.out.println("Parent class cons");
        }
    }
    class Dogy extends Animal implements Serializable{
        Dogy(){
             System.out.println("Child class constructor");
         }
         int j = 20;
    }
    
  3. 输出:
    父母阶层利弊 子类构造函数
    序列化
    反序列化
    父母阶层利弊 10 ----- 999

    从上面看,有3例在儿童被序列化而非父母时发生。

    案例1:在序列化期间,JVM会检查是否有任何实例变量来自非序列化父类。如果是这样,父类不可序列化并且其实例变量参与序列化,则jvm忽略实例变量的值并将默认值存储在文件中。 (在上面的例子中,i在文件中存储为0)。

    案例2:在反序列化期间,JVM检查是否有任何实例变量来自非序列化父类。如果是这样,JVM将运行INSTANCE CONTROL FLOW并恢复对象的原始值。

    实例控制流程(简称)http://java2bigdata.blogspot.in/2015/05/instance-control-flow-in-java.html
    1.实例成员的识别。
    2.执行实例变量赋值&amp;实例。
    3.执行构造函数。

    情况3:由于在实例控制流中,执行构造函数。因此,在Non serialized parent的情况下,调用no-arg构造函数,该构造函数可以是用户提供的或jvm创建的。如果没有no-arg构造函数,那么它将导致InvalidClassException。

答案 3 :(得分:1)

我们不需要一个no-arg构造函数,而父类是可序列化的。

但是当子序列化而不是父级时,我们必须在父级中使用no-arg const来在反序列化时根据需要设置值,否则我们将具有默认值。

答案 4 :(得分:0)

如果Parent类具有Seri​​alizable行为,那么默认情况下,所有子类都具有Seri​​alizable行为。

class Parent implements Serializable{

    int x;

}

class Children extends Parent{

    int m;
    public static void main(String args[]){
    Children c = new Children();
    c.m =10;
    c.x =20;
    // Enter Serialization Code;
    // Enter De serialization Code;
}
}

注意:读取反序列化对象时,您将能够检索序列化状态。