简体   繁体   English

如果序列化是在层次结构中继承的,则将调用未实现可序列化的类的构造函数。 为什么会这样呢?

[英]If the serialization is inherited in a hierarchy then the constructor of class not implementing serializable will be called. Why is this so?

Why is constructor of the Food and Fruit class called when I deserialize where as the constructor of SkinFruit and Banana2 is not called in the below example? 当我反序列化以下示例中的SkinFruit和Banana2的构造函数时,为什么要调用Food and Fruit类的构造函数?

Suppose I have following class hierarchy 假设我有以下课程层次结构

class Food{
  public Food() { System.out.println("1"); } 
    }

class Fruit extends Food {
    public Fruit() { System.out.print("2"); }
}

class SkinFruit extends Fruit implements Serializable{
    SkinFruit() { System.out.print("3"); }
}
public class Banana2 extends SkinFruit { 
  private static final long serialVersionUID = 1L;
  int size = 42;

     public static void main(String [] args) {
       Banana2 b = new Banana2();
       FileOutputStream fost;
        try {
            fost = new FileOutputStream(new File("d:/testbanana.ser"));
            ObjectOutputStream oostr= new ObjectOutputStream(fost);
            oostr.writeObject(b);
            oostr.flush();          
            oostr.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }catch (IOException e) {
            e.printStackTrace();
        }

        try {
            FileInputStream fin= new FileInputStream(new File("d:/testbanana.ser"));
            ObjectInputStream objin= new ObjectInputStream(fin);
             b=(Banana2)objin.readObject();

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }


       System.out.println(" restored "+ b.size + "" );
     }
}

Because that's how (de)serialization works. 因为这就是反序列化的工作方式。 It is a separate mechanism from regular object construction. 它是与常规对象构造不同的机制。

If the constructor of Class A is called, that's because Class A itself does not implement Serializable . 如果调用了Class A的构造函数,那是因为Class A本身未实现Serializable During Deserialization, the parameterless constructor of the first non-serializable class in the inheritance hierarchy is called (possibly that of java.lang.Object ). 反序列化期间,将调用继承层次结构中第一个不可序列化类的无参数构造函数(可能是java.lang.Object无参数构造函数)。 If that class does not have a parameterless constructor, there will be an Exception. 如果该类没有无参数的构造函数,则将发生异常。

Neither is called, because your class is not Serializable. 两者都不被调用,因为您的类不可序列化。

You cannot call the B() without calling A() because B calls A. 您不能不调用B()就调用A()因为B调用了A。

Consider the following program 考虑以下程序

public static void main(String... args) throws Exception {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(new B());
    oos.writeObject(new D());
    oos.close();
    System.out.println("-------------");
    ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
    System.out.println("deserialize B");
    ois.readObject();
    System.out.println("deserialize D");
    ois.readObject();
}

static class A {
    public A() {
        System.out.println("Inside class A");
    }
}

static class B extends A  implements Serializable {
    public B() {
        System.out.println("Inside class B");
    }
}

static class C implements Serializable  {
    public C() {
        System.out.println("Inside class C");
    }
}

static class D extends C {
    public D() {
        System.out.println("Inside class D");
    }
}

prints 版画

Inside class A
Inside class B
Inside class C
Inside class D
-------------
deserialize B
Inside class A
deserialize D

A is the non Serializable parent of B. It is not Serialized and so the constructor has to be called to set any fields which need to be set. A是B的不可序列化的父级。它没有被序列化,因此必须调用构造函数以设置需要设置的任何字段。 However, B, C and D are all Serializable and their fields have been serializable and will be reset. 但是,B,C和D都是可序列化的,并且它们的字段已被序列化并将被重置。 There is no need to call the constructor. 无需调用构造函数。

If at all you want to re-create some information when the object is being deserialized, you should use the below method implementation inside your Serializable class. 如果您要在反序列化对象时完全重新创建一些信息,则应在Serializable类中使用以下方法实现。 For instance, put the below code inside B . 例如,将下面的代码放入B

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
    System.out.println("Resurrecting B");
}

The other one is for serialization, just in case you want to do some stuff before the object gets written off. 另一个用于序列化,以防万一您想在对象被注销之前做一些事情。

private void writeObject(ObjectOutputStream out) throws IOException {
    // do stuff.
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 反序列化时,父类(未实现序列化接口)构造函数被调用两次 - While deserilization, Parent class(Not implementing the Serialization interface) constructor are called twice 为什么序列化无需实现Serializable就可以工作 - Why does serialization work without implementing Serializable 如果基类(未实现可序列化)的子类实现可序列化,为什么基类(未实现可序列化)应该没有参数构造函数? - Why base class(not implementing Serializable) should have no argument constructor if its subclass implements Serializable? 为什么序列化过程需要访问第一个不可序列化的超类的无参数构造函数? - Why does Serialization process require access to a no argument constructor of the first non serializable super class? Spring @ExceptionHandler(Exception.class)总是被调用。 为什么? - Spring @ExceptionHandler(Exception.class) always gets called. Why? 自定义继承类的序列化 - custom serialization of inherited class 为什么可序列化的内部类不可序列化? - Why is a serializable inner class not serializable? 继承类中的泛型和构造函数 - Generics and constructor in the inherited class 继承类中的构造方法调用 - Constructor invocation in the inherited class 实现Serializable的类不能是readObject - Class implementing Serializable cannot readObject
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM