單例模式-枚舉


那么現在再寫一種最受歡迎的單例模式,即枚舉單例模式。

枚舉模式的代碼如下:

date是為了測試方便。

public enum  EnumInstance {
    INSTANCE;
    private Object date;

    public Object getDate() {
        return date;
    }

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

1、那么我們可以寫一個序列化的栗子進行測試。

public class SerivalTest {
    public static void main(String[] args) throws IOException, ClassNotFoundException {
        EnumInstance instance = EnumInstance.getInstance();
        instance.setDate(new Object());
        //放文件
        ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream("single_file"));
        outputStream.writeObject(instance);

        //取文件
        File file = new File("single_file");
        ObjectInputStream inputStream = new ObjectInputStream(new FileInputStream(file));
        EnumInstance hungrySingleton = (EnumInstance) inputStream.readObject();

        System.out.println(instance);
        System.out.println(hungrySingleton);
        System.out.println(instance==hungrySingleton);
    }
}

 結果為:

 

怎么樣?枚舉就是這么強大,那么序列化和反序列化對枚舉是怎么處理的呢?首先通過inputStream.readObject()進入,找到readEnum()方法。

如下:

是通過類型和name進行獲得枚舉常量,因為枚舉中的name是唯一的,並且對應一個枚舉常量,所以2012行拿到的肯定是唯一的常量對象,

這樣呢就沒有創建新的對象。維持了這個對象的單例屬性。枚舉中這個處理方法還是很簡單的,而且很容易理解,所以枚舉類對於序列化

這個破壞是不受影響的。

 

 

 2、寫一個反射攻擊的例子。

public class Testreflection {
    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class object = EnumInstance.class;
        Constructor constructor = object.getDeclaredConstructor();
        constructor.setAccessible(true);

        EnumInstance instance = EnumInstance.getInstance();
        EnumInstance newInstance = (EnumInstance) constructor.newInstance();

        System.out.println(instance.getDate());
        System.out.println(newInstance.getDate());
        System.out.println(instance.getDate() == newInstance.getDate());

     }
    }

看結果:

 

表示沒有獲得無參構造器,那么我們打開源碼看一哈。java.lang.enum  可以看到枚舉沒有無參構造器,而且僅有一個傳兩個參數的構造器,如下所示。那么我們就將這兩個參數傳進去,再測試。

 

 

可以看到又拋了額一個異常,但是可以很清楚的了解到這個異常是說不能反射去創建對象,我們從報錯的地方進入源碼查看詳情。

 

源碼清清楚楚的告訴我們如果是枚舉類型,就拋出異常,可見枚舉是多么的強大!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM