Java:何时在序列化期间添加readObjectNoData()?

Vin*_*C M 23 java serialization effective-java

我正在阅读"Effective Java"中的序列化章节.我试图理解书中的下一段.

如果您实现的类具有可序列化和可扩展的实例字段,那么您应该注意这一点.如果类的实例字段初始化为其默认值(整数类型为零,布尔值为false,对象引用类型为null),则会违反不变量,必须将此readObjectNoData方法添加到类中:

    // readObjectNoData for stateful extendable serializable classes
     private void readObjectNoData() throws InvalidObjectException {
             throw new InvalidObjectException("Stream data required");
     }
Run Code Online (Sandbox Code Playgroud)

我不确定上述陈述的含义.

为了测试这个,我创建了一个Person类(可序列化和可扩展)

   class Person   implements Serializable{

       private String name;

       private int age;

      Person() {
         this("default",1);
      }


     Person(String name, int y) {
       this.name = name;
        this.age = y;
      }
    }
Run Code Online (Sandbox Code Playgroud)

以及扩展它的类Employee.

     class Employee extends Person  {

      String address ;


    public Employee()
    {
        super();
        address ="default_address";
    }

    public Employee(String name , int age, String address)
    {
        super(name,age);
        this.address = address;
    }
           }
Run Code Online (Sandbox Code Playgroud)

我创建的Person类中是否有任何不变量?什么时候会被侵犯?我复制粘贴了Employee类中的readObjectData()方法的代码,但它从未被调用过.何时调用readObject()方法?我错过了什么吗?

Mis*_*ble 22

Java对象序列化规范中的readObjectNoData部分看起来很有趣(见下文).

您对该问题的编辑提供了一个完美的例子.如果Employeeserialized,当它并未扩大Person,后来deserialized当它没有那么Person部分将被初始化为空字符串,0岁.使用此方法,您可以将它们分别初始化为"name"和1.

对于可序列化对象,readObjectNoData方法允许类在反序列化子类实例的情况下控制其自己字段的初始化,并且序列化流不会将所讨论的类列为反序列化对象的超类.如果接收方使用与发送方不同版本的反序列化实例的类,并且接收方的版本扩展了未由发送方版本扩展的类,则可能发生这种情况.如果序列化流已被篡改,也可能发生这种情况; 因此,尽管存在"恶意"或不完整的源流,readObjectNoData仍可用于正确初始化反序列化对象.

private void readObjectNoData() throws ObjectStreamException;

每个可序列化的类可以定义自己的readObjectNoData方法.如果可序列化类没有定义readObjectNoData方法,那么在上面列出的情况下,类的字段将被初始化为它们的默认值(如JavaTM语言规范第二版第4.5.5节所列); 当引入对readObjectNoData方法的支持时,此行为与JavaTM 2 SDK,Standard Edition 1.4版之前的ObjectInputStream的行为一致.如果可序列化类确实定义了一个readObjectNoData方法并且出现了上述条件,则在反序列化期间将调用readObjectNoData,否则将调用类定义的readObject方法,如果该类已将该类列为流的超类正在反序列化的实例.