枚舉來實現單例模式

枚舉來實現單例模式

前面咱們說到序列化和反序列化以及反射對單例都是有破壞的,下面咱們介紹一種更加優雅的實現,也是effective java中推薦的實現方式,枚舉實現單例模式。話很少說咱們直接看代碼吧。java

public enum EnumInstance {
    INSTANCE{
        protected void printTest(){
            System.out.println("redstar Print SingletonTest");
        }
    };
    protected abstract void printTest();
    private Object data;

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
    public static EnumInstance getInstance(){
        return INSTANCE;
    }

}
複製代碼

而後咱們看看測試類測試

public class SingletonTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
    
    EnumInstance instance = EnumInstance.getInstance();
        instance.setData(new Object());

        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("singleton_file"));
        oos.writeObject(instance);

        File file = new File("singleton_file");
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file));
        EnumInstance newInstance = (EnumInstance) ois.readObject();
        
        
        
        System.out.println(instance.getData());
        System.out.println(newInstance.getData());
        System.out.println(instance.getData() == newInstance.getData());
    }
複製代碼

這裏返回的結果是true,而後咱們測試一下反射去獲取這個對象。this

public class SingletonTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class objectClass = EnumInstance.class;
        Constructor constructor = objectClass.getDeclaredConstructor(String.class,int.class);
        constructor.setAccessible(true);
        EnumInstance instance = (EnumInstance) constructor.newInstance("redstar",666);
}
複製代碼

運行結果報異常spa

Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects at java.lang.reflect.Constructor.newInstance(Constructor.java:417)code

咱們點擊進去查看一下417行的代碼對象

if ((clazz.getModifiers() & Modifier.ENUM) != 0)
            throw new IllegalArgumentException("Cannot reflectively create enum objects");
        ConstructorAccessor ca = constructorAccessor; 
複製代碼

從這裏咱們能夠看到jdk底層就爲咱們對反射進行處理了。get

相關文章
相關標籤/搜索