Venkat Teki
Venkat Teki

Reputation: 2783

Deserializing a singleton in java

I am going through Effective Java, and came across this example.

class Elvis implements Serializable {
    public static final Elvis  inst = new Elvis();
    private Elvis() {
        System.out.println("In elvis constructor ");
    }

    public static Elvis getInstance() {
        return inst;
    }
}

According to the book, when i deserialize, a new ELVIS object should be constructed, but i see the constructor is not called at the time of deserialization?

Here is my code which serializes, and deserializes.

FileOutputStream fos = new FileOutputStream("myserial1.txt");
ObjectOutputStream oos = new ObjectOutputStream(fos);
Elvis e = Elvis.getInstance();
System.out.println(" e = "+e.getInstance());

oos.writeObject(e);

System.out.println("Serialization done.");
FileInputStream fis = new FileInputStream("myserial1.txt");
ObjectInputStream ois = new ObjectInputStream(fis);
Elvis el = (Elvis) ois.readObject();
System.out.println(" el = "+el.getInstance());

I See both e and e1 are priting the same reference, and constructor is invoked only once.

Am i misunderstanding the concept here?

Please help.

Upvotes: 8

Views: 9852

Answers (4)

ShijuJohn1093
ShijuJohn1093

Reputation: 33

Since Read and Write operation both are executed in same jvm instance and class was already loaded for the read operation and the static fields are store atclass level So here static variable inst is never required to re instantiated public static final Elvis inst = new Elvis();

So same reference are return which were attached with the class level

Upvotes: 0

Filipp Voronov
Filipp Voronov

Reputation: 4197

During serialization no constructor is called, fields initialized by deserialization process or readObject() method (if you add this method into your class). If you want to implement a serializable singleton, you should additionally add readResolve() method as it described here.


PS.
Keep in mind that getInstance() is a static method of class Elvis, so such calls as e.getInstance() and el.getInstance() are equals to Elvis.getInstance().

Upvotes: 9

Aniket Thakur
Aniket Thakur

Reputation: 68935

According to the book, when i deserialize, a new ELVIS object should be constructed,
but i see the constructor is not called at the time of deserialization?

First of all Object creation and constructor invocation are two separate thing. In normal scenario when you create an object with new keyword Object is first created and then constructor is invoked. You can see the bytecodes of any java class in which an object is created.

Now as for your question, in Serialization object is created like any other object and instead of running constructor values/state is restored using reflection. So basically values are read from stream(persistent storage is your case) and injected into the object using reflection.

Upvotes: 0

Rohit Jain
Rohit Jain

Reputation: 213261

Am i misunderstanding the concept here?

What you are misunderstanding is that a constructor creates an object. No it doesn't. Constructor just initializes the object. Now, deserialization need not invoke the constructor, as it already has the state of the serialized object, and that is what it has to provide us.

However, if in the hierarchy of serializable class, there is some non-serializable class, then it's constructor would be invoked to initialize the state in that class, as it has not been serialized.

You can go through the Serialization Specification.

Upvotes: 1

Related Questions