通过枚举实现单例模式

  • 时间:
  • 浏览:
  • 来源:互联网

通过枚举实现单例模式

对于饿汉式单例模式和懒汉式单例模式了解的同学,使用以上两种单例模式,我们均可以通过反射的方式破坏单例模式的特性。那么,如何才能避免程序开发中使用反射的方式破坏单例的这种行为呢?接下来用过枚举的方式来创建的单例模式就可以避免上述的问题。

直接上代码:

public enum EnumSingleton {
    INSTANCE;
    //枚举类可以自定义一些属性
    private Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }

    public static EnumSingleton getInstance() {
        return INSTANCE;
    }

}

我们尝试使用反射的方式创建实例,看是否能够创建成功:

public class EnumSingletonTest {
    public static void main(String[] args) {
        EnumSingleton enumSingleton=EnumSingleton.getInstance();
        enumSingleton.setData(new Object());
        System.out.println("创建单例模式:"+enumSingleton);
        try{
            Class clazz= EnumSingleton.class;
            Constructor c=clazz.getDeclaredConstructor(String.class,int.class);
            c.setAccessible(true);
            Object object=c.newInstance();
            System.out.println(object);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

会出现以下报错:

java.lang.IllegalArgumentException: Cannot reflectively create enum objects
	at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
	at com.example.singleton.EnumSingletonTest.main(EnumSingletonTest.java:16)

我们直接定位到报错源码的位置(Constructor.java:417)发现如下内容:

    public T newInstance(Object ... initargs)
        throws InstantiationException, IllegalAccessException,
               IllegalArgumentException, InvocationTargetException
    {
        if (!override) {
            if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {
                Class<?> caller = Reflection.getCallerClass();
                checkAccess(caller, clazz, null, modifiers);
            }
        }
        if ((clazz.getModifiers() & Modifier.ENUM) != 0)
            throw new IllegalArgumentException("Cannot reflectively create enum objects");

也就是说,在通过反射调用方法newInstance()创建实例时,源码会对class的修饰符做一个判断(clazz.getModifiers() & Modifier.ENUM) != 0)。如果创建实例的类是用enum修饰的,那么不能通过反射创建实例(Cannot reflectively create enum objects)

本文链接http://www.dzjqx.cn/news/show-617065.html