我正在尝试了解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
只是使您免于编写无聊的代码。