is it possible to serialize a singleton object?
It depends on how the singleton is implemented. If your singleton is implemented as an enum type with one element, then it is by default:
// Enum singleton - the preferred approach
public enum Elvis {
INSTANCE;
public void leaveTheBuilding() { ... }
}
If your singleton is not implemented using a single-element enum type but, say using a static factory method (the variant is to use a public static final field):
// Singleton with static factory
public class Elvis {
private static final Elvis INSTANCE = new Elvis();
private Elvis() { ... }
public static Elvis getInstance() { return INSTANCE; }
public void leaveTheBuilding() { ... }
}
Then it is not sufficient to add implements Serializable
to make it serializable, you must declare all instance fields transient (to prevent a serialization attack) and provide a readResolve
method.
To maintain the singleton guarantee,
you have to declare all instance
fields transient and provide a
readResolve
method (Item 77).
Otherwise, each time a serialized
instance is deserialized, a new
instance will be created, leading, in
the case of our example, to spurious
Elvis sightings. To prevent this, add
this readResolve
method to the Elvis
class:
// readResolve method to preserve singleton property
private Object readResolve() {
// Return the one true Elvis and let the garbage collector
// take care of the Elvis impersonator.
return INSTANCE;
}
This is heavily discussed in Effective Java (which also shows the serialization attack):
- Item 3: Enforce the singleton property with a private constructor or an enum type
- Item 77: For instance control, prefer enum types to readResolve
in which scenario should we serialize a singleton
For example for temporary, short-term storage or for transporting objects over a network (with RMI, for example).
And is it possible to design a class whose object can not be serialized.
As others said, don't implement Serializable
. And even if an object or one of its superclasses implements Serializable
, you can still prevent it from being serialized by throwing a NotSerializableException
from writeObject()
.