一尘不染

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

java

我正在阅读“有效Java”中的序列化一章。我试图理解本书中的以下段落。

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

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

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

为了测试这一点,我创建了一个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;
      }
    }

还有一个扩展它的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;
    }
           }

我创建的Person类中是否有任何不变式?什么时候会受到侵犯?我在Employee类中复制了readObjectData()方法的代码,但从未被调用。什么时候调用readObject()方法?我想念什么吗?


阅读 278

收藏
2020-12-03

共1个答案

一尘不染

Java对象序列化规范中的readObjectNoData部分似乎很有趣(请参阅下文)。

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

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

private void readObjectNoData() throws ObjectStreamException;

每个可序列化的类都可以定义自己的readObjectNoData方法。如果可序列化的类未定义readObjectNoData方法,则在上述情况下,该类的字段将被初始化为其默认值(如JavaTM语言规范第二版第4.5.5节中列出);当引入了对readObjectNoData方法的支持时,此行为与JavaTM
2
SDK标准版1.4之前的ObjectInputStream的行为一致。如果可序列化的类确实定义了readObjectNoData方法,并且出现了上述情况,

2020-12-03