簡體   English   中英

了解Java中的單例類

[英]Understanding singletons class in Java

在閱讀Effective Java時,我發現實現單例的最有用方法只是使用具有單個INSTANCE enum 但是如果需要將其設為一個類,根據他的一些懷疑,完美的可序列化線程安全的單例類將如下所示:

public class SerializableSingletonClass implements Serializable{
    private static final long serialVersionUID = 1L;
    private int value;
    private String name;

    private SerializableSingletonClass(int value, String name) {
        if( value < 0 ) throw new IllegalArgumentException("Value may not be less than 0");
        this.value = value;
        this.name = Validate.notNull(name, "Name may not be null");
    }

    private static class SerializableSingletonHolder{
        public static final SerializableSingletonClass INSTANCE;
        static {
            INSTANCE = new SerializableSingletonClass(0, "default");
        }
    }

    private void readObject(ObjectInputStream stream) throws InvalidObjectException{
        throw new InvalidObjectException("proxy required");
    }

    private Object writeReplace(){
        return new SerializationProxy(this);
    }

    private static class SerializationProxy implements Serializable{
        private static final long serialVersionUID = 1L;
        public SerializationProxy(SerializableSingletonClass ignored) { } //Here is the question

        private Object readResolve(){
            return SerializableSingletonHolder.INSTANCE;
        }
    }
}

據我所知,他建議只用當前使用的實例替換序列化的實例。

因此,為什么我們永遠都不能使單例序列化,因為它們的序列形式將永遠不會被使用。 我們只是將其丟棄,並用當前實例替換反序列化的實例。

對我來說,實現可序列化單例的問題看起來只是一個理論上的問題。 根據我的說法,對單例進行反序列化沒有多大意義(對於enum )。

那我想念什么呢? 您能否詳細解釋一下?

如果您在其他一些可序列化的類中有某個字段存儲該單例實例,並且想要對該類進行序列化/反序列化,則始終必須標記該字段為transient ,並確保在反序列化時手動填充它。 如果在Singleton中處理它,則不必這樣做。 我想這就是可序列化單例的原因。

枚舉也可以序列化,而不是它們的字段。

我認為保持簡單和易於維護非常重要,例如,如果要保存它,請使用文本文件。

我將添加一個保存和加載之類的方法(可能帶有文件名)

enum SaveableSingleton {
    INSTANCE;

    String name;
    int value;

    public void load(String filename) throws IOException {
        try (Scanner scanner = new Scanner(new File(filename))) {
            name = scanner.nexLine();
            value = scanner.nextInt();
        }
    }

    public void save(String filename) throws IOException {
        try (PrintWriter pw = new PrintWriter(new File(filename))) {
            pw.println(name);
            pw.println(value);
        }
    }
}

創建一個像

my-name-is
12345

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM