java序列化化指南

来源:互联网 发布:绝地大逃杀有mac版吗 编辑:程序博客网 时间:2024/04/29 18:03
一.Java序列化方式
1.默认方式序列化
1)实现serializable接口
2)实现序列化的代价:
降低该类的灵活性
增加了错误和不安全的可能
增加测试负担
如果不可序列化类的子类要实现序列化,父类必须要提供一个无参的构造函数。
3)UID的作用,其实该字段除了可以在序列化过程中加速判断错误,其他时间毫无意义,比如即使UID一样,但是你增加一个字段还是不会报错,比如你减少一个字段,照样报错,当然在自定义序列化方式的时候,你需要兼容默认序列化方式。

2.自定义序列化方式
比如序列化一个List结构的类,就应该考虑是否使用自定义序列化方式
通过transient修饰,就可以从默认序列化方式中被忽略。

下面我们以ArrayList的自定义序列化方式来说明问题:
private transient E[] elementData;//将elementDate从默认序列化方式中忽略,优化性能,节省序列化空间/**     * Save the state of the <tt>ArrayList</tt> instance to a stream (that     * is, serialize it).     *     * @serialData The length of the array backing the <tt>ArrayList</tt>     *             instance is emitted (int), followed by all of its elements     *             (each an <tt>Object</tt>) in the proper order.     */    private void writeObject(java.io.ObjectOutputStream s)        throws java.io.IOException{int expectedModCount = modCount;// Write out element count, and any hidden stuffs.defaultWriteObject();        // Write out array length        s.writeInt(elementData.length);// Write out all elements in the proper order.for (int i=0; i<size; i++)            s.writeObject(elementData[i]); if (modCount != expectedModCount) {    throw new ConcurrentModificationException();}    }    /**     * Reconstitute the <tt>ArrayList</tt> instance from a stream (that is,     * deserialize it).     */    private void readObject(java.io.ObjectInputStream s)        throws java.io.IOException, ClassNotFoundException {// Read in size, and any hidden stuffs.defaultReadObject();        // Read in array length and allocate array        int arrayLength = s.readInt();        Object[] a = elementData = (E[])new Object[arrayLength];// Read in all elements in the proper order.for (int i=0; i<size; i++)            a[i] = s.readObject();    }


3.readobject方法安全性问题
当你在反序列化回来的时候,可以传2个引用过来,虽然引用时final类型的,但是某些final类型引用的值是可以改变的,比如Date类型,所以会造成不安全的事件发生。
解决方法:
1.在readobject的时候,将引用对象克隆
start = new Date(start.getTime());

这样外部引用就失效了。
2.通过readResolve方法来解决
readResolve方法的作用是,抛弃反序列化回来的对象引用,将该对象垃圾收集,然后使用该方法返回的新对象引用,看起来比较酷。并且可以很好的解决单例模式无法反序列化的问题。
0 0
原创粉丝点击