Sington class serialization
To change the Singleton class to serializable, it is not enough to implement the Serializable interface only. To maintain Singleton, you must provide a readResolve method for the Singleton class. Otherwise, a serialized instance will generate a new instance for each deserialization. Singleton is no exception.
Through the serializable tools, someone can write a singleton instance to disk, and then read it back up, using tively getting a new instance. even though the constructor is private, the serializable tools have special access to create instances of a class regardless. serialization has a special hook it uses-a private method on the class being instantiated calledreadResolve () -which is meant to supply a 'hook' for a class developer to ensure that they have a say in what object is returned by serialization. oddly enough, readResolve () is not static, but is instead invoked on the new instance just created by the serialization. we'll get into that in a minute-for now, here is how our readResolve () method works with our singleton:
As follows:
Java code
Import java. io. FileInputStream;
Import java. io. FileOutputStream;
Import java. io. ObjectInputStream;
Import java. io. ObjectOutputStream;
Import java. io. ObjectStreamException;
Import java. io. Serializable;
// Singleton with final field
Public class Singleton implements Serializable {
Private static final long serialVersionUID = 5765648836796281035L;
Public static final Singleton uniqueInstance = new Singleton ();
Private Singleton (){
}
//... Remainder omitted
Public static void main (String [] args) throws Exception {
// Serialization
ObjectOutputStream objectOutputStream = new ObjectOutputStream (new FileOutputStream ("D: \ Singleton. obj "));
Singleton singleton = Singleton. uniqueInstance;
ObjectOutputStream. writeObject (singleton );
ObjectOutputStream. close ();
// Deserialization
ObjectInputStream objectInputStream = new ObjectInputStream (new FileInputStream ("D: \ Singleton. obj "));
Singleton singleton2 = (Singleton) objectInputStream. readObject ();
ObjectInputStream. close ();
// Compare the original Instance
System. out. println (singleton = singleton2 );
}
}
The output result is: false.
The solution is to add readResolve () to the Singleton class:
Java code
// The readResolve method maintains Singleton attributes.
Private Object readResolve () throws ObjectStreamException {
Return uniqueInstance;
}
Test again: the output result is true.
After deserialization, the newly created object will call this method first. The object reference returned by this method is returned, replacing the newly created object. Essentially, this method ignores the newly created object and returns the instance created during class initialization.