Question

I have a pretty simple class hierarchy:

public class DropdownOption<T> /* does NOT implement Serializable */ {
    private T value;
    private String label;

    public DropdownOption() {
        this (null, null);
    }

    public DropdownOption(T value, String label) {
        this.value = value;
        this.label = label; 
    }

    public T getValue() {
        return value;
    }

    public void setValue(T value) {
        this.value = value;
    }

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }
}

/**
 * Convenience decorator
 */
public class LongIdDropdownOption extends DropdownOption<Long> 
    implements Serializable {

    private static final long serialVersionUID = -3920989081132516015L;

    public LongIdDropdownOption() {
        super();        
    }

    public LongIdDropdownOption(Long value, String label) {
        super(value, label);
    }

    public Long getId() {
        return getValue();
    }

    public void setId(Long id) {
        super.setValue(id);
    }
}

When I create a new instance of the LongIdDropdownOption, which does implement Serializable; serialize it; and then immediately deserialize it -- then the deserialized object has both of its fields set to null:

public void testSerialization() throws Exception {
    LongIdDropdownOption option = new LongIdDropdownOption(1L, "One");         

    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    ObjectOutputStream os = new ObjectOutputStream(buffer);
    os.writeObject(option);
    os.close();

    ObjectInputStream is = new ObjectInputStream(
        new ByteArrayInputStream(buffer.toByteArray()));
    LongIdDropdownOption result = (LongIdDropdownOption) is.readObject();
    is.close();

    assertNotNull(result);        
    assertEquals("One", result.getLabel()); /** Fails, label is null */
}

When I make the base class implement Serializable, the code starts working correctly. My question is... why ?

Was it helpful?

Solution

As described here - http://java.sun.com/developer/technicalArticles/ALT/serialization "one common reason to override readObject and writeObject is to serialize the data for a superclass that is not Serializable itself".

The state that you think you have in your subclassed instance isn't really visible to the serialization as its not going via your API or reflection. As far as serialization process is concerned the state belongs in the super class that does not implement Serializable. This is where you lose it.

Here's a link to a Java Object Serialization Specification that should explain it: http://download.oracle.com/javase/6/docs/platform/serialization/spec/serialTOC.html

OTHER TIPS

Because since only the child class implements Serializable, only its fields will be serialized by the JVM. The JVM does not see the parent members as members of the child class, as it uses reflection to list the class' fields.

From Java Docs Here

If class A does not implement Serializable but a subclass B implements Serializable, will the fields of class A be serialized when B is serialized?

Only the fields of Serializable objects are written out and restored. The object may be restored only if it has a no-arg constructor that will initialize the fields of non-serializable supertypes. If the subclass has access to the state of the superclass it can implement writeObject and readObject to save and restore that state.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top