请参阅下面的片段
USPresident usPresident = new USPresident(56);
try (ObjectOutputStream oos = new ObjectOutputStream(new
FileOutputStream("/home/nikhil/dev/USPresident.data"))){
oos.writeObject(usPresident);
usPresident.setTerm(57);
oos.writeObject(usPresident);
System.out.println("Serialized");
}
创建了一个任期为56的President实例。对其进行序列化。将该术语重置为57,再次对其进行序列化
但是,当我反序列化该对象时,它仍然具有术语56(而不是57!)。
我看了书就明白了
是的,即使您使用设置器将术语更改为57并再次序列化,它也会打印56。发生这种情况的原因是serialVersionUID,在序列化时由JVM检查了它。如果一个类已被序列化,而您尝试再次对其进行序列化,则JVM将不会对其进行序列化。
但是,据我了解,serialVersionUID用于检查反序列化过程中Class对象是否与序列化对象匹配。同样,serialVersionUID用作对象签名的标识符,而不是状态。
不明白这里发生了什么。有人可以解释这种行为吗?
看了ObjectOutputStream的实现,这就是writeObjet的实现方式
public final void writeObject(Object obj) throws IOException {
if (enableOverride) {
writeObjectOverride(obj);
return;
}
try {
writeObject0(obj, false);
} catch (IOException ex) {
if (depth == 0) {
writeFatalException(ex);
}
throw ex;
}
}
参见boolean enableOverride。编写“修改”对象必须为真。但是,仅当使用将ObjectOutputStream子类化时,才可以将其设置为true。请参阅下面的受保护的构造函数,
protected ObjectOutputStream() throws IOException, SecurityException {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
bout = null;
handles = null;
subs = null;
enableOverride = true;
debugInfoStack = null;
}
为什么会有这种奇怪的行为?
您的书有误,而serialVersionUID
静态的,则用于处理类本身的不同版本。
序列化的想法是获取一个活动对象(由指向的对象usPresident
)并将其所有状态保存为某种外部形式(字节,XML,JSON)。然后,您可以将该状态转换回该对象的副本。就像将文件保存在文字处理器中一样。
但是,如果在序列化对象后修改该对象,则不会建立连接。您已经将字节写出到磁盘,并且它们不会更改,因为您在对象上调用了方法。当从这些字节重新创建对象时,该对象将具有与保存对象时相同的值。如果您忘记将更改保存到文字处理文档中,则磁盘上的文件仍然具有旧内容。
在您的情况下,您正在Java序列化中遇到一个怪癖,因为您将同一对象多次写入同一个对象ObjectOutputStream
。为了使您可以序列化复杂的对象关系,Java序列化仅将对象保存一次,然后在再次保存时链接回该对象。关闭并重新打开流,您应该看到更新的值。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句