我正在尝试了解Java序列化机制,我对此几乎没有疑问

请回答以下有关Java序列化的问题:


为什么我们使用oos.defaultWriteObject();?根据this post,此处存在向后兼容性。我还不太了解它是如何实现的。序列化的不兼容更改之一是删除较新版本中的字段。这意味着旧版本将不得不设置有时对用户无效的默认值。这与新版本添加一个新字段并允许设置默认值有何不同?
在自定义序列化过程中,同时使用oos.defaultWriteObject();oos.writeObject(address);会不会有什么区别呢?我的意思是都将所有超类和当前类的非瞬态非静态字段都写入OOS。


这里

private void writeObject(java.io.ObjectOutputStream stream)
        throws IOException {
    stream.writeObject(name);
    stream.writeInt(id);
    stream.writeObject(DOB);
}

private void readObject(java.io.ObjectInputStream stream)
        throws IOException, ClassNotFoundException {
    name = (String) stream.readObject();
    id = stream.readInt();
    DOB = (String) stream.readObject();
}


上面的代码产生与下面的代码相同的结果

private void writeObject(java.io.ObjectOutputStream stream)
            throws IOException {
        stream.defaultWriteObject();
    }

    private void readObject(java.io.ObjectInputStream stream)
            throws IOException, ClassNotFoundException {
         stream.defaultReadObject();
    }


什么时候使用这两种方法,什么时候只使用writeObject(employee); // employee是我的整个对象//


这是可能无法回答我的问题的重复问题列表。
question 1它表示*如果在写入可选数据(如果有)之前没有一次调用defaultWriteObject或writeFields,那么在ObjectInputStream *的情况下实例反序列化的行为是不确定的,但是我仍然可以调用writeObject而不使用deafultwriteobject.right ?
question 2这些答案表示defaultwriteobject方法将写入一些额外的数据以流式传输,并以反射方式检查要写入的内容。 oos.writeobject(object obj)也不反省吗?
最后,我可以通过重写writeObject和ReadObject方法来控制序列化,那么Externalizable的意义何在?
如果提供串行versionUID不会引发异常,如果我反序列化一个对象,而该对象缺少具有该字段的旧类的字段,将会发生什么情况,如果我提供自己的SerialverUID,基本上所有不兼容的更改将发生什么?是否具有自己的串行版本UID不会针对所有兼容更改抛出streamcorrupted异常?

最佳答案

你的问题


writeObject不是为了向后兼容。 readObject是。
他们是一样的。 defaultWriteObject是为了帮助您快速编写“可序列化”的值。


向后兼容

考虑您的bean添加了一个新字段。

class Bean implements Serializable {
  int id;
  String name;
  String newValue = "123";
}


尽管已提供newValue默认值,但是Java序列化将忽略它。 (因为它分配实例而不是new

现在,如果您不使用readObject,您将得到newValue=null。因此,您还需要在readObject处进行初始化。

  private void readObject(ObjectInputStream stream) throws Exception {
    stream.defaultReadObject();
    this.newValue = "123";
  }


defaultWriteObject如何为您提供帮助

考虑到您的bean除了某些字段外几乎可以“序列化”。

请参阅以下代码。 BadThing不是Serializable,或者它包含一些您不想序列化的敏感数据。

class Bean implements Serializable {
  int id;
  String string;
  BadThing badThing;
}


要快速序列化它,可以让字段transient并编写writeObject方法来处理它

  private void writeObject(ObjectOutputStream stream) throws Exception {
    stream.defaultWriteObject();
    stream.writeInt(badThing.id);
  }

  // Corresponding `readObject`


当然,您可以将defaultWriteObject替换为多个writeXXX。但是,如果您有很多领域,那么编写代码既累又无聊,对吗?

因此,defaultWriteObject只是使您免于编写无聊的代码。

09-25 21:25