In an interview the interviewer asked me the following question: is it possible to serialize a singleton object? I said yes, but in which scenario should we serialize a singleton?
And is it possible to design a class whose object can not be serialized?
Deserialization. In serialization, we can save the object of a byte stream into a file or send over a network. Suppose if you serialize the Singleton class, and then again de-serialize that object, it will create a new instance, hence deserialization will break the Singleton pattern.
Defining readResolve() method ensures that we don't break singleton pattern during DeSerialization process.
Question 7) Can you Customize the Serialization process or can you override default Serialization process in Java? The answer is yes you can. We all know that for serializing an object ObjectOutputStream. writeObject (saveThisobject) is invoked and for reading object ObjectInputStream.
What happens if you try to send non-serialized Object over network? When traversing a graph, an object may be encountered that does not support the Serializable interface. In this case the NotSerializableException will be thrown and will identify the class of the non-serializable object.
The question should probably be better phrased as "is it possible to use serialization and deserialization with a singleton-pattern class C in a way that does not break the singleton pattern?"
The answer is basically yes:
import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectStreamException; import java.io.Serializable; public class AppState implements Serializable { private static AppState s_instance = null; public static synchronized AppState getInstance() { if (s_instance == null) { s_instance = new AppState(); } return s_instance; } private AppState() { // initialize } private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ois.defaultReadObject(); synchronized (AppState.class) { if (s_instance == null) { // re-initialize if needed s_instance = this; // only if everything succeeds } } } // this function must not be called other than by the deserialization runtime private Object readResolve() throws ObjectStreamException { assert(s_instance != null); return s_instance; } public static void main(String[] args) throws Throwable { assert(getInstance() == getInstance()); java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream(); java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(baos); oos.writeObject(getInstance()); oos.close(); java.io.InputStream is = new java.io.ByteArrayInputStream(baos.toByteArray()); ObjectInputStream ois = new ObjectInputStream(is); AppState s = (AppState)ois.readObject(); assert(s == getInstance()); } }
but note that it is possible for multiple instances of AppState
to exist using this code. However, only one is referenced. The others are eligible for garbage collection, created only by the deserialization runtime, so they don't exist for practical purposes.
For answers to your other two questions (In which scenario should we serialize a singleton? Is it possible to design a class whose object can not be serialized?), see @Michael Borgwardt's answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With