Java: practical possibilities for serializing Singletons?
The object can be single point, but it can be part of a larger structure that it doesn't quite know. For example, it can implement an interface that can have several different implementations (and therefore instances):
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);
}
}
Now, suppose we need StringSink
one that dumps lines to stdout. Since there is only one stdout, we could also make it single:
/** 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); }
}
And we use it like this:
MultiDumper dumper = new MultiDumper(StdoutStringSink.INSTANCE);
If you are going to serialize and then deserialize this dump truck, you will have two instances StdoutStringSink
to move around in your program.
source to share
The most common case would be if you have an object that represents a large data structure (for example, a tree of nodes in an XML-style document).
This data structure can easily contain monochromatic values (for example, single instances that represent the data type of a particular attribute attached to a node in a tree). Many different nodes in the tree can point to the same common singleton value.
There are many circumstances where you can serialize a data structure like this, for example. sending a copy of the object over the network. In this case, you also need to serialize the singleton values.
But then, when you read the data structure again, you want to use the existing singleton value, not the newly created instance. This is why you needreadResolve()
source to share
Joshua Bloch Effective Java (2nd Edition) suggests using Enum as a singleton. It is always created by the VM and it is not possible (or difficult) to create a second instance of a singleton.
For a regular singleton, you can always "hack" the system, see
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.
source to share