Transient Fields in Classes

COMP 310    Java Resources  Eclipse Resources

(Back to the RMI Overview)

A field in a class can be marked with "transient" modifier to indicate that its value should NOT be included when the class is serialized.

Example:

public class MyDataObject implements IDataObject {
    private transient IViewAdapter viewAdpt;

    // etc.
}

In this case, we mark the view adapter of this class to be transient because if we transmit this object off to another machine (the "target"), the view adapter that the object originally had, which would have connected it to the original machine's GUI, would be invalid on the target machine where the transmitted object is being deserialized.    Thus we want Java's serializer to simply ignore the viewAdpt field when serializing MyDataObjects.

The use of the transiet modifier is also handy when you want to serializer to stop at a certain level and to keep the serializer from attempting to serialize parts of your system that you do not want to be serialized or are not serializable.

A Problem During Deserialization

The problem with transient fields is that because they are ignored, by default, when the transmitted object is deserialized, the field is left as null, which is often not a desired state for the object.    What we need is a way to override the deserialization process to set the transient field(s) to well-defined values to insure robust, predictable behavior of the deserialized objects.

To do so, we override the built-in deserialization behavior by defining a special method called readObject, which is automatically called during the deserialization process by Java.   This method is added to the class with the transient field:

public class MyDataObject implements IDataObject {
    private transient IViewAdapter viewAdpt;
    
    // etc.

    private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
        stream.defaultReadObject(); // Deserialize the non-transient data
        viewAdpt = IViewAdapter.NULL_ADAPTER; // re-initialize the transient field to a well-defined value
    }
}

Here, the first step is to let Java do what it normally does by calling stream.defaultReadObject().    This will take care of the proper deserialization of all the non-transient fields in MyDataObject.

The next step is to set the transient field, which is null at that point, to a well-defined value, here, the no-op, "null adapter" instance of the IViewAdapter (implemented as a static field in the interface, as much such "null objects" are).   Now, if the MyDataObject is used before its viewAdpt is set to a new adapter that connects to the target machine's GUI, you won't get a "null pointer exception" but a nice controllable no-op instead.

 

 

© 2020 by Stephen Wong