序列化单例模式的实现————readResolve 源码解读
在可序列化类中加上 readResolve 方法,就可以实现单例模式了!这是为什么呢?让我们一起看看源码中的奥秘吧!
继续上篇单例模式的测试。
只有实现了序列化接口 Serializable ,才可以进行 序列化操作,
测试代码
序列化单例模式【测试】
先注释掉下面的代码(单例代码在上篇文章有 单例之序列化模式)
执行 testSerializableSingleton
方法,结果如下图,序列化和反序列化出来的不是同一个对象,违背了单例模式,也就是说,在这种情况下通过序列化模式可以破坏单例模式.
源码
readObject
接着我们来看看为什么要加上面注释掉的代码,
进入 Object o = objectInputStream.readObject();
进入上面红框中的方法 readObject0
,它是 readObject 的底层实现方法,
在该方法中中找到下图
readOrdinaryObject
来到上图中的方法readOrdinaryObject
,继续往下看
这里会去判断有没有这个无参构造器,有的话 obj 不为 null,会执行下图中的代码
这里会去判断有没有这个 hasReadResolveMethod
,有的话会通过反射方法
invokeReadResolve
去创建这个对象,最后将 obj 的引用地址指向当前创建的对象rep
,最后 return
出去。
invokeReadResolve
我们来看看invokeReadResolve
做了什么
通过注释可知,它会去调用所表示的可序列化类的 readResolve
方法,在 idea 中通过通过ctrl+鼠标左键
点击readResolveMethod
方法,选择getInheritableMethod
可以看到下图
了解到该方法是一个 参数argTypes
为空,返回类型为 Object
的函数,那他的修饰符(modifier)是什么呢?
可以知道该方法如果是 static
或者 ABSTRACT
就直接返回 null
,
抽象方法没有方法体,它需要非抽象子类去实现它,就直接返回null
了,
那为什么static
也返回null
呢!希望看到该博文的大神们帮忙答疑!!🐖谢谢!!
这个我想了好久也想不出答案来。。 直到我重新看到它的方法名 getInheritableMethod
:获取可以继承的方法🙃
猜测:
static 方法修饰后它就属于类了,无法被重写,也无法在使用时动态绑定了,如:class A 实现了序列化接口,并定义了
readResolve
方法,class B 和 C 都继承了 A ,此时反序列化 B,反序列化的过程会去调用这个invokeReadResolve
方法,通过该方法进行反射调用,如果readResolve
方法是static
这时会找不到该方法的。🐷
对猜测进行验证,弄一个简单的继承关系测试下!如图:
输出结果如下图:
**解析:**很明显这里 getDeclaredMethods
是获取不到任何方法的,因为这个只能获取到 B 自己声明的一些方法。
而源码中(上上张图😄)是通过这个getDeclaredMethod
方法去获取的!通过反射的知识点我们知道,该方法只能获取该类自己定义的方法。
其他访问修饰符也是符合对应的权限才会返回该方法的。
最后
欢迎小伙伴们来一起探讨问题~
如果你觉得本篇文章还不错的话,那拜托再点点赞支持一下呀😝
让我们开始这一场意外的相遇吧!~
欢迎留言!谢谢支持!ヾ(≧▽≦*)o 冲冲冲!!
我是 4ye 咱们下期应该……很快再见!! 😆
如果文章对您有所帮助,欢迎关注公众号 J a v a 4 y e 😆
版权声明: 本文为 InfoQ 作者【4ye】的原创文章。
原文链接:【http://xie.infoq.cn/article/a1f6449e390333c3a991d38e4】。文章转载请联系作者。
评论