Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Why doesn't deserialization invoke constructor & what's the best workaround?

The Java serialization spec for Java 1.5 said:

For serializable objects, the no-arg constructor for the first non-serializable supertype is run. For serializable classes, the fields are initialized to the default value appropriate for its type. Then the fields of each class are restored by calling class-specific readObject methods, or if these are not defined, by calling the defaultReadObject method. Note that field initializers and constructors are not executed for serializable classes during deserialization.

However, this means if we put a static variable (for example a counter variable) inside the class, it will not be updated as normally would:

class Foo {
    static int t;

    public Foo() {
        t++;
    }
}

public class Bar extends Foo implements Serializable {
    static int t;

    public Bar() {
        t++;
    }
}

In this case, if one instance of Bar is deserialized, then the counter for Foo is correct and the counter for Bar is off-by-one.

I wonder why does deserialization does not invoke the constructor? Since it seems that while this will gain a bit on speed, it can cause potential problems. The compiler could be easily designed to produce a "static constructor" that only updates the static variables that will be updated and does not rely on outside information when the class is loaded.

Also, I wonder what is the best way to avoid this? The solution I can think of is packing the deserialization with the operation on the static variable.

Thanks for any inputs in advance!

like image 533
zw324 Avatar asked Aug 22 '11 18:08

zw324


People also ask

Why constructor is not called during deserialization in Java?

The deserialization process does not use the object's constructor - the object is instantiated without a constructor and initialized using the serialized instance data.

Does constructor of class gets called during deserialization?

Constructors and deserialization When we de-serialize an object, the constructor of its class is never called.

Does deserialization create new object?

When you deserialize your object, the object will create a new entry in heap which will not have any references to any of the objects.

What happens when you serialize and deserialize an object?

Serialization is a mechanism of converting the state of an object into a byte stream. Deserialization is the reverse process where the byte stream is used to recreate the actual Java object in memory. This mechanism is used to persist the object.


2 Answers

Deserialization doesn't invoke the constructor because the purpose of it is to express the state of the object as it was serialized, running constructor code could interfere with that.

like image 145
Nathan Hughes Avatar answered Oct 13 '22 03:10

Nathan Hughes


Without going in to the philosophy of why a constructor is not called (objects without default constructors, for example, should be Serializable) the standard way of working around problems with the default behavior is to provide your own readObject() or writeObject() implementations for your class.

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException
{
    in.defaultReadObject();
    t++;
}
like image 43
antlersoft Avatar answered Oct 13 '22 04:10

antlersoft