##简介 java序列化与反序列化相当简单,实现serializable接口即可.序列化和反序列化主要用于不同系统的之间的通信,可以让对象以流的形式进行传输,一个系统接受之后,然后反序列化成对象,获取相应的属性,完成相应的动作.然java内部的实现,可能会消耗很多内存.
###谨慎实现序列化
实现uid,使用IDE自己生成的UID(序列化版本号);
注意读取的安全,因为程序可能会访问正在构造中的对象;
需注意相应的序列化版本不兼容问题;
内部类不需要实现序列化,
如果不是专门用于序列化的实体类,不要实现序列化接口.
###考虑使用自定义的序列化形式
1.避免类导出的API束缚在该类的内部表示法上,提高扩展性;
2.避免消耗过多的时间和空间
3.避免引起栈溢出
####如何自定义序列化方法
private void writeObject(ObjectOutputStream s )throws IOException{ s.defaultWriteObject(); //其他输出内部字段的代码}private void readObject(ObjectInputStream s){ s.defaultReadObject(); //其他读取内部字段的代码}
默认的序列化方法会序列化并输出每个非transient域;默认的反序列化方法会读取并转化每个非transient域.
对于transient域,请自定义其输出和读取;
###保护性编写readObject方法
-
readObject()方法可以认为是一个以字节流作为唯一参数的构造器.
-
你必须为你的readObject()方法提供保护性拷贝和有效性检查.
-
对于非final的类,readObject()方法不应该调用其非final方法,因为重写可能会导致失败;
-
可以使用ObjectInputValidation接口对反序列化之后的类进行验证.
###使用序列化代理来替代序列化实例
当你必须在一个不能被客户端扩展的并带有约束条件的类上编写readObject或writeObject方法时,就必须考虑使用序列化代理模式.
序列化代理,在目标类外建立一个私有静态嵌套类,
package com.wangge.serialize;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InvalidObjectException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.OutputStream;import java.io.Serializable;import java.util.Date;public class Period implements Serializable { private static final long serialVersionUID = -2072208249014270392L; private final Date start; private final Date end; public Period(Date start, Date end) { super(); this.start = new Date(start.getTime()); this.end = new Date(end.getTime()); } public Date getStart() { return new Date(this.start.getTime()); } public Date getEnd() { return new Date(this.end.getTime()); } private Object writeReplace() { return new SerializationProxy(this); } private void readObject(ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required"); } @Override public String toString() { return "Period [start=" + start + ", end=" + end + "]"; } private static class SerializationProxy implements Serializable { private static final long serialVersionUID = -2072208249014270314L; private final Date start; private final Date end; SerializationProxy(Period p) { this.start = p.start; this.end = p.end; } private Object readResolve() { return new Period(start, end); } } public static void main(String[] args) { try { ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(bos); out.writeObject(new Period(new Date(), new Date())); byte[] ref = { 0x71, 0, 0x70, 0, 5 }; bos.write(ref); ref[4] = 4; bos.write(ref); ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(bos.toByteArray())); Object period = in.readObject(); System.out.println(period); Object ob = in.read(); System.out.println(ob); } catch (IOException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } }}
缺点:1.不能被客户端扩展的类兼容,不能在序列化中被调用;2.会降低性能.