这段程序表示了一个可序列化的类继承自一个非序列化的有状态超类,期望的结果是,子类序列化以后传输并反序列化回来,原先的值域包括超类的值域都保持不变。
但是输出是:
Java代码
x :10;y :50
z :100
x :0 ;y :0
z :100 结果和期望不符,子类的值域保留下来了,但是超类的值域丢失了,这对jvm 来说是正常的,因为超类不可序列化;为了解决这个问题,只能自定义序列化行为,具体做法是在SerializeDemo里加入以下代码:
Java代码
private void writeObject(ObjectOutputStream os ) throws IOException
{
os.defaultWriteObject ();//java对象序列化默认操作
os.writeInt (getX());
os.writeInt (getY());
}
private void readObject (ObjectInputStream is) throws IOException
,ClassNotFoundException {
is.defaultReadObject();//java对象反序列化默认操作
int x=is.readInt();
int y=is.readInt();
super.init(x ,y );
} writeObject 和readObject方法为JVM 会在序列化和反序列化java对象时
会分别调用的两个方法,修饰符都是private ,没错。我们在序列化的默认动作之后将超类里的两个值域x 和y 也写入object流;与之对应在反序列化的默认操作之后读入x 和y 两个值,然后调用超类的初始化方法。
再次执行程序之后的输出为:
Java代码
x :10;y :50
z :100
x :10;y :50
z :100 另外还有两个自定义序列化方法writeReplace和readResolve ,分别用来在序列化之前替换序列化对象和在反序列化之后的对返回对象的处理。一般可以用来避免singleTon 对象跨jvm 序列化和反序列化时产生多个对象实例,事实上singleTon 的对象一旦可序列化,它就不能保证singleTon 了。JVM 的Enum实现里就是重写了readResolve 方法,由JVM 保证Enum的值都是singleTon 的,所以建议多使用Enum代替使用writeReplace和readResolve 方法。
Java代码
private Object readResolve()
{
return INSTANCE ;
}
private Object writeReplace (){
return INSTANCE ;
}
注:writeReplace调用在writeObject 前;readResolve 调用在readObject
之后。
① 凡本网注明稿件来源为"原创"的所有文字、图片和音视频稿件,版权均属本网所有。任何媒体、网站或个人转载、链接转贴或以其他方式复制发表时必须注明"稿件来源:我考网",违者本网将依法追究责任;
② 本网部分稿件来源于网络,任何单位或个人认为我考网发布的内容可能涉嫌侵犯其合法权益,应该及时向我考网书面反馈,并提供身份证明、权属证明及详细侵权情况证明,我考网在收到上述法律文件后,将会尽快移除被控侵权内容。