枚举类的单例模式可以很好的防止序列化反序列化对单例模式的破坏,以及反射对单例模式的破坏。
具体代码如下
package Singleton;
public enum EnumInstance {
INSTANCE;
private Object data;
public Object getData() {
return data;
}
public void setData(Object data) {
this.data=data;
}
public static EnumInstance getInstance() {
return INSTANCE;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
我们利用jad工具对这个枚举类进行反编译,得到如下
// Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://www.kpdus.com/jad.html
// Decompiler options: packimports(3)
// Source File Name: EnumInstance.java
package Singleton;
public final class EnumInstance extends Enum
{
private EnumInstance(String s, int i)
{
super(s, i);
}
public Object getData()
{
return data;
}
public void setData(Object data)
{
this.data = data;
}
public static EnumInstance getInstance()
{
return INSTANCE;
}
public static void main(String args1[])
{
}
public static EnumInstance[] values()
{
EnumInstance aenuminstance[];
int i;
EnumInstance aenuminstance1[];
System.arraycopy(aenuminstance = ENUM$VALUES, 0, aenuminstance1 = new EnumInstance[i = aenuminstance.length], 0, i);
return aenuminstance1;
}
public static EnumInstance valueOf(String s)
{
return (EnumInstance)Enum.valueOf(Singleton/EnumInstance, s);
}
public static final EnumInstance INSTANCE;
private Object data;
private static final EnumInstance ENUM$VALUES[];
static
{
INSTANCE = new EnumInstance("INSTANCE", 0);
ENUM$VALUES = (new EnumInstance[] {
INSTANCE
});
}
}
可以看出:
1、该类是final类,不允许继承
2、构造器是private的
3、INSTANCE在类加载时,就通过静态块初始化了,所以不存在延迟加载
通过ObjectInputStream和ObjectOutputStream写入,读出测试得到序列化和反序列化不会产生新到的对象实例,因为ObjectInputStream源码当中有个Enum的判断,所以很好的实现了单例模式。并且,也不允许反射得到构造器方法进行实例化对象,所以这是一种比较好的方式实现单例模式。