本文将与您分享关于Java自定义序列化行为的示例分析的内容。我觉得边肖很实用,就和大家分享一下作为参考。让我们跟着边肖看一看。
通常情况下,一个类实现java序列化非常简单,只需要实现Serializable接口,然后在跨jvm传输的过程中,根据默认的java序列化规则对该类进行序列化和反序列化。不同的jvm版本有稍微不同的序列化方法,但是它们基本上是兼容的。
在某些特殊情况下,可能需要自定义序列化和反序列化的行为。请参见以下示例:
Java代码
classabstractserializedmo { private intx,y;publicvoidinit(intx,inty){ this . x=x;this.y=y} publiintgetx(){ returnx;} publiintgety(){ returny;} public void prinxy(){ system . out . println(' x : ' x ';y : ' y);} } public class serializedemoextendsabstractserializedemoimplementserializable { privateintz;public serialisedemo(){ super . init(10,50);z=100}nbsp
; public void printZ() { super.printXY(); System.out.println("z:" + z); } public static void main(String[] args) throws IOException, ClassNotFoundException { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bos); SerializeDemo sd = new SerializeDemo(); sd.printZ(); out.writeObject(sd); ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); SerializeDemo sd2 = (SerializeDemo) in.readObject(); sd2.printZ(); } }
这段程序表示了一个可序列化的类继承自一个非序列化的有状态超类,期望的结果是,子类序列化以后传输并反序列化回来,原先的值域包括超类的值域都保持不变。
但是输出是:
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之后。
感谢各位的阅读!关于“Java自定义序列化行为的示例分析”这篇文章就分享到这里了,希望
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/133163.html