Java:序列化单身人士的实际用例?

时间:2012-03-30 06:15:03

标签: java serialization singleton use-case

我们继续阅读有关如何使用'readResolve()'来确保序列化Singleton时的单一性。但是,想要首先序列化Singleton的实际用例是什么?

编辑:pl。注意:问题是为什么序列化Singleton,而关于什么是安全的方法。

3 个答案:

答案 0 :(得分:3)

最常见的情况是您有一个表示大型数据结构的对象(例如XML样式文档中的节点树)。

此数据结构可以轻松包含单例值(例如,表示附加到树中节点的特定属性的数据类型的单例实例)。树中的许多不同节点可以指向相同的共享单例值。

在许多情况下,您可能希望序列化此类数据结构,例如:通过网络发送对象的副本。在这种情况下,您还需要序列化单例值。

但是当你再次读取数据结构时,你想要使用单例的现有值,而不是新创建的实例。这就是您需要readResolve()

的原因

答案 1 :(得分:2)

Joshua Bloch Effective Java (2nd Edition)建议使用Enum作为单身人士。它总是由VM创建,并且不可能(或很难)创建单例的第二个实例。

对于普通单身人士,您可以随时“破解”系统,请参阅:

Singleton Pattern

Hot Spot:
Multithreading - A special care should be taken when singleton has to be used in a multithreading application.
Serialization - When Singletons are implementing Serializable interface they have to implement readResolve method in order to avoid having 2 different objects.
Classloaders - If the Singleton class is loaded by 2 different class loaders we'll have 2 different classes, one for each class loader. 
Global Access Point represented by the class name - The singleton instance is obtained using the class name. At the first view this is an easy way to access it, but it is not very flexible. If we need to replace the Sigleton class, all the references in the code should be changed accordinglly.

答案 2 :(得分:1)

对象可以是单例,但它可能是较大结构的一部分,但不太了解它。例如,它可以实现可以具有多个不同实现(以及实例)的接口:

interface StringSink extends Serializable { void dump(String s); }

class MultiDumper implements Serializable {
    private final StringSink sink;
    public MultiDumper(StringSink sink){ this.sink = sink; }
    void doSomeStuff(Collection<String> strings){
        for (String s : strings) sink.dump(s);
    }
}

现在,假设我们想要一个将字符串转储到stdout的StringSink。由于只有一个标准输出,我们不妨将其设为单例:

/** Beware: Not good for serializing! */
class StdoutStringSink {
    public static final StdoutStringSink INSTANCE = new StdoutStringSink();
    private StdoutStringSink(){}
    @Override
    public void dump(String s){ System.out.println(s); }
}

我们这样使用它:

MultiDumper dumper = new MultiDumper(StdoutStringSink.INSTANCE);

如果您要序列化,然后反序列化此转储程序,则程序中会有两个StdoutStringSink个实例。