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 ?
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