美文网首页设计模式
单例模式与序列化

单例模式与序列化

作者: Ludwigvan | 来源:发表于2017-10-25 10:38 被阅读89次

    设计模式之单例模式中,简单介绍了什么是单例模式,怎样实现自己的单例模式,在文中也提到一个关键点,不知道大家注意没有:序列化和反序列化会影响破坏单例模式。这里先给结论待会再给大家解释为什么?因为反序列化的时候会去反射调用对象的无参构造方法。

    今天带着几个问题来学习:

    1、怎么实现序列化?

    2、transient关键字的作用?

    3、如何自定义序列化?

    4、自定义的序列化是如何被调用的?为什么就生效了?

    5、ArrayList的序列化思想有什么好处?

    一、如何实现序列化?

    在Java中要如果我们要涉及到文件操作或者网络传输都离不开序列化,他会保证我们序列化和反序列后得到的对象一致。要实现序列化也简单,Java从1.1版本开始就提供了一个接口 java.io.Serializable,只要我们实现这个接口就能实现序列化。


    二、transient关键字的作用

    在实现了Serializable接口的类中,所有被transient关键字修饰的属性都不会被序列化和反序列化(注意:序列化只会关注在对象的状态上面,即动态属性,静态属性由于是在JVM装载类的时候就会初始化,所有不会实例化。)

    写一个被序列化的User类,注释都写的比较清楚了。

    在main方法中写一个测试User方法:

    readObejct方法是把一个对象写到一个文件中在读取出来返回:

    下面运行这个方法:

    可以看到name 和 sex 被序列化了 但是age 为什么为“null”呢?应该age 没有被序列化进去,反序列化的时候会有默认值,除了基本类型如int=0外其他的对象类型都是null;

    那么问题来了,对ArrayList源码了解的朋友应该看到:

    这个elemntData就是数组元素,序列化的时候也是把所有的elementData序列化到文件;明明有transient为什么可以被序列化呢?

    readObejct还是刚刚那个相同的方法。

    可以看到都被序列化出来了这是为什么呢?

    这里先给结论:

    在序列化过程中,如果被序列化的类中定义了writeObject和readObject方法,虚拟机会试图调用对象类里的writeObject和readObject方法,进行用户自定义的序列化和反序列化。

    如果没有这样的方法,则默认调用是ObjectOutputStream的defaultWriteObject方法以及ObjectInputStream的defaultReadObject方法。

    用户自定义的writeObject和readObject方法可以允许用户控制序列化的过程,比如可以在序列化的过程中动态改变序列化的数值。

    我们能够注意到在ArrayList源码中有这样的方法:

    好吧,即使你有这两个方法,但是为什么我序列化的时候就会调用这两个方法了在哪里调用的呢?

    这里大家就要去看ObjectOutputStream和ObjectInputsStream的源码了,调用链是:writeObejct —>writeObject0—>writeOrdinary—>ObjectwriteSerialData——>invokeWriteObject;

    最好亲自去看看这个调用链,里面大有玄机。

    好啦之前的三个问题也都解决了:

    如何自定义序列化?只要实现自己的readObject或者writeObject 就行了。

    自定义的如何被调用的?就是在ObjectOutputStream的输出的时候调用的他会去看有没有用户自定义的writeObject,如果没有就会调用默认的。有就调用用户自定义的。

    那么为什么ArrayList 要用这种方式来序列化呢?

    不知道大家注意看上面的代码没有?有这样一段:List<String> list =new ArrayList<String>(100);

    这里为什么我初始化了100个size的大小,序列化反序列化后输出的就五个呢?对的,实际只放了五个元素,那就会序列化95个null元素。为了保证在序列化的时候不会将这么多null同时进行序列化。

    文章开始的问题:为什么序列化会影响单例模式:

    在invokeWriteObject 中使用了反射去创建新的对象;解决的方式就是在序列化的类中添加readRsolve

    方法;其实最好的实现单例的方式就是枚举还不用添加这个方法。

    相关文章

      网友评论

        本文标题:单例模式与序列化

        本文链接:https://www.haomeiwen.com/subject/dogfpxtx.html