为了账号安全,请及时绑定邮箱和手机立即绑定

Singleton模式序列化问题?

Singleton模式序列化问题?

郎朗坤 2019-04-13 08:45:45
单例实现的一种方式:私有构造器,公有静态工厂方法publicclassSingleton2{privatestaticfinalSingleton2INSTANCE=newSingleton2();//私有静态final域/**私有构造器*/privateSingleton2(){}/**公有静态工厂方法*/publicstaticSingleton2getInstance(){returnINSTANCE;}}为了使利用这种方法实现的Singleton类变成可序列化的,仅仅在申明中加上“implementsSerializable”是不够的。为了维护并保证Singleton,必须声明所有的实例域都是transient,并提供一个readResolve()方法,否则,每次反序列化一个序列化的实例时都会创建一个新的实例。这段话是effectivejava中的描述,我不理解的是为什么仅仅加上implementsSerializable不行呢,反序列化一个序列化的实例时会创建一个新的实例?--补充问题:关于这种单例模式有一种评论如下:这种方式基于classloder机制避免了多线程的同步问题,不过,instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法,但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到lazyloading的效果。这里的其他方式还可以是什么?
查看完整描述

2 回答

?
慕盖茨4494581

TA贡献1850条经验 获得超11个赞

1为什么仅仅加上implementsserializable不行
这种方式的单例模式构建的基础是封装性,如何实现单例呢?由于构造函数变为了私有,外部无法构造,只能通过Singleton2.getInstance()来获取,这样实现了单列,但是序列化时是这样吗?序列对象如何知道调用getInstance()来获取对象呢?我们来看看java底层序列化的实现,打开JDK中类ObjectStreamClass(这个类是负责序列化类对象的)
privatestaticObjectStreamField[]getSerialFields(Classcl)
throwsInvalidClassException
{
ObjectStreamField[]fields;
if(Serializable.class.isAssignableFrom(cl)&&
!Externalizable.class.isAssignableFrom(cl)&&
!Proxy.isProxyClass(cl)&&
!cl.isInterface())
{
if((fields=getDeclaredSerialFields(cl))==null){
fields=getDefaultSerialFields(cl);
}
Arrays.sort(fields);
}else{
fields=NO_FIELDS;
}
returnfields;
}
再往下跟踪可以明显看出他是用反射方式来序列化,用反射方式,不是调用getinstance(),当然单例就失效了
2每次反序列化一个序列化的实例时都会创建一个新的实例
由于反序列化时也是用反射,所有当然每一个对象会创建一个新的实例
                            
查看完整回答
反对 回复 2019-04-13
  • 2 回答
  • 0 关注
  • 379 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号