先给出老师的饿汉式枚举封装的单例代码。
public class EnumStarvingSingleton {
private EnumStarvingSingleton(){}
public static EnumStarvingSingleton getInstance(){
return ContainerHolder.HOLDER.instance;
}
private enum ContainerHolder{
HOLDER;
private EnumStarvingSingleton instance;
ContainerHolder(){
instance = new EnumStarvingSingleton();
}
}
}
再给出我的测试用例:
public class SingletonDemo {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Constructor constructor = EnumStarvingSingleton.class.getDeclaredConstructor();
constructor.setAccessible(true);
EnumStarvingSingleton instance1 = (EnumStarvingSingleton) constructor.newInstance();
EnumStarvingSingleton instance2 = EnumStarvingSingleton.getInstance();
System.out.println(instance1 == instance2);
}
}
我的测试用例结果是false,说明反射已经破坏了该单例模式。
一般用枚举类型抵御反射对单例的破坏,直接用枚举就行了,如下述代码所示:
public enum Singleton {
INSTANCE
}
测试代码如下:
public class SingletonDemo {
public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
Constructor constructor = Singleton.class.getDeclaredConstructor(String.class, int.class);
constructor.setAccessible(true);
Singleton instance1 = (Singleton) constructor.newInstance();
Singleton instance2 = Singleton.INSTANCE;
System.out.println(instance1 == instance2);
}
}
上述测试会抛出IllegalArgumentException异常,因为枚举类无法通过反射来创建实例。
不知道为什么老师这里要多一层封装,把枚举作为私有的内部类来处理?