首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

第3条-用私有构造器可能枚举类型强化Singleton属性

2013-07-04 
第3条--用私有构造器或者枚举类型强化Singleton属性?学习这条首先要了解什么是Singleton,Singleton就是仅

第3条--用私有构造器或者枚举类型强化Singleton属性

?

学习这条首先要了解什么是Singleton,Singleton就是仅仅被实例化一次的类,我们先来看一个常见的单例:

public class Singleton {    public final static Singleton INSTANCE = new Singleton();        private Singleton(){            }}

?

这样的单例其实并不能完全保证该类只被实例化一次,攻击者可以通过反射获得私有的构造器,并执行setAccessible(true)方法使其能够被访问,这就破坏了单例只能被实例化一次的特性。解决这个问题就是在私有的构造器中判断被执行的次数,不是第一次执行时候就抛出异常。

还有一种情况是有的单例需要被序列化,即实现java.io.Serializable接口。单例的对象被反序列化时就会创建新的实例。

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton.txt"));oos.writeObject(Singleton.INSTANCE);      ObjectInputStream ois = new ObjectInputStream(new FileInputStream("singleton.txt"));Singleton sin = (Singleton)ois.readObject();

?
这里的sin就是一个新的实例,解决这个问题需要将单例中所有非基本类型的域都加transient修饰符,表明这些域都不需要被序列化,同时要在类中加入readResolve方法返回唯一的实例:

private Object readResolve(){  return INSTANCE;}

?

这样就能保证反序列化得到的对象也是那个唯一的实例,至于为什么会在后面序列化的章节专门有一条做阐释。

通过上面的分析过程,大家会发现实现一个完美的单例太复杂了,幸运的是,JDK1.5之后,我们有了更好的方式来实现单例,那就是枚举类型:

public enum EnumSingleton{  INSTANCE;}

?
这种方法再简单不过了,不需要考虑反射攻击的情况,而且无偿地提供了序列化机制,绝对防止多次实例化,所以在以后实现单例的时候优先地考虑枚举吧!

把枚举用作单实例,没这么玩过,学习了。果然没有查到枚举如何进行反射。

热点排行