Java自定义序列化行为解析
来源:互联网 发布:cf检测游戏数据异常 编辑:程序博客网 时间:2024/04/30 17:21
The original website:http://longdick.iteye.com/blog/1018051
正常情况下,一个类实现java序列化很简单,只需要implements Serializable接口即可,之后该类在跨jvm的传输过程中会遵照默认java序列化规则序列化和反序列化;不同jvm版本之间序列化方式稍有不同,但基本上都是兼容的。
在某些特殊情况下,可能需要自定义序列化和反序列化的行为,看下面例子:
- class AbstractSerializeDemo {
- private int x, y;
- public void init(int x, int y) {
- this.x = x;
- this.y = y;
- }
- public int getX() {
- return x;
- }
- public int getY() {
- return y;
- }
- public void printXY() {
- System.out.println("x:" + x + ";y:" + y);
- }
- }
- public class SerializeDemo extends AbstractSerializeDemo implements Serializable {
- private int z;
- public SerializeDemo() {
- super.init(10, 50);
- z = 100;
- }
- 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();
- }
- }
class AbstractSerializeDemo { private int x, y; public void init(int x, int y) { this.x = x; this.y = y; } public int getX() { return x; } public int getY() { return y; } public void printXY() { System.out.println("x:" + x + ";y:" + y); }}public class SerializeDemo extends AbstractSerializeDemo implements Serializable { private int z; public SerializeDemo() { super.init(10, 50); z = 100; } 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(); }}
这段程序表示了一个可序列化的类继承自一个非序列化的有状态超类,期望的结果是,子类序列化以后传输并反序列化回来,原先的值域包括超类的值域都保持不变。
但是输出是:
- x:10;y:50
- z:100
- x:0;y:0
- z:100
x:10;y:50z:100x:0;y:0z:100
结果和期望不符,子类的值域保留下来了,但是超类的值域丢失了,这对jvm来说是正常的,因为超类不可序列化;
为了解决这个问题,只能自定义序列化行为,具体做法是在SerializeDemo里加入以下代码:
- 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);
- }
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两个值,然后调用超类的初始化方法。
再次执行程序之后的输出为:
- x:10;y:50
- z:100
- x:10;y:50
- z:100
x:10;y:50z:100x:10;y:50z:100
另外还有两个自定义序列化方法writeReplace和readResolve,分别用来在序列化之前替换序列化对象 和 在反序列化之后的对返回对象的处理。一般可以用来避免singleTon对象跨jvm序列化和反序列化时产生多个对象实例,事实上singleTon的对象一旦可序列化,它就不能保证singleTon了。JVM的Enum实现里就是重写了readResolve方法,由JVM保证Enum的值都是singleTon的,所以建议多使用Enum代替使用writeReplace和readResolve方法。
- private Object readResolve()
- {
- return INSTANCE;
- }
- private Object writeReplace(){
- return INSTANCE;
- }
private Object readResolve() { return INSTANCE; } private Object writeReplace(){ return INSTANCE; }
注:writeReplace调用在writeObject前;readResolve调用在readObject之后。
- Java自定义序列化行为解析
- java 自定义序列化
- Java序列化之自定义序列化
- JSON的自定义序列化和解析
- Protostuff自定义序列化(Delegate)解析
- java 自定义序列化字段
- Java 序列化机制解析
- Java序列化全面解析
- 解析java序列化机制
- Java序列化Serializable解析
- JAVA自定义序列化的神奇方法
- Java多种方式自定义序列化
- Java多种方式自定义序列化
- Java序列化之自定义序列化2
- Java实现自定义序列
- Gson解析之自定义序列化和反序列化
- Java对象序列化详细解析
- Java序列化的作用解析
- 指定的命名连接在配置中找不到、非计划用于 EntityClient 提供程序或者无效
- 天津市部分机关负责人出席“中外大使夫人迎新春联谊会”
- 虚拟化之ESXI配置备份
- 【MSDN】ASP.NET Web 服务、企业服务和 .NET Remoting 的性能比较测试与建议
- InstallAnywhere 2009 Enterprise build 3783如何破解
- Java自定义序列化行为解析
- 百度原创性内容判断的失误
- 图解苹果iOS 5的24个秘密功能(图)
- Windows SharePoint Services 3.0内容迁移:导出内容
- Yii命令行应用程序设计
- Posix线程编程指南
- 删除两个双向链表中值相同的结点--无空白头结点
- 用In.js颗粒化管理、加载你的Javascript模块
- 实用的网页背景图片拉伸css(总结4种)