Serialization and subclassing

Interfaces and classes designed for inheritance should rarely implement Serializable, since this would force a significant (and often unwanted) task on their implementors and subclasses.

However, even though most abstract classes don't implement Serializable, they may still need to allow their subclasses to do so, if desired.

There are two cases. If the abstract class has no state, then it can simply provide a no-argument constructor to its subclasses. If the abstract class has state, however, then there's more work to be done, as demonstrated in the following example.

Example

public abstract class Government {

  public Government(String winningParty) {
    init(winningParty);
    //never invoke an overridable method in a constructor
  }

  public final void raiseTaxes() {
    validateInit(); //always called by public methods
    //..elided
  }

  public final void lowerTaxes() {
    validateInit();
    //..elided
  }

  /**
  * A template method which calls a protected abstract method, to
  * be overridden by subclasses.
  */
  public boolean makeLaw(){
    validateInit();
    String bill = draftLegislation(); //protected, abstract method
    return vote(bill);
  }

  // PROTECTED

  /**
  * Each governament will draft legislation in a particular way.
  * A tyranny, for example, would not have wide debate between its
  * citizens.
  */
  protected abstract String draftLegislation();

  /**
  * This no-argument constructor is needed by subclass's Serialization
  * mechanism.
  */
  protected Government() {
    //empty
  }

  /**
  * Called by both this class's public constructor, and by a subclass's
  * readObject method. Note this method is final.
  */
  protected final void init(String winningParty){
    if (isInitialized) {
      throw new IllegalStateException("Cannot call init twice.");
    }
    this.winningParty = winningParty;
    this.isInitialized = true;
  }

  /**
  * Subclass will need access to the superclass's internal state,
  * either through public or protected gets. Note that the
  * get needs to be final.
  */
  protected final String getWinningParty() {
    return winningParty;
  }

  // PRIVATE
  private String winningParty;
  private boolean isInitialized = false;

  /**
  * Must be called by public methods.
  */
  private void validateInit() throws IllegalStateException {
    if (!isInitialized) {
      throw new IllegalStateException("Uninitialized object");
    }
  }

  private boolean vote(String bill){
    return true; //toy implentation
  }
} 

import java.io.*;

/** A Serializable subclass. */
public final class Tyranny extends Government implements Serializable {

  public Tyranny(String winningParty) {
    super(winningParty);
  }

  // PROTECTED

  protected String draftLegislation() {
    return "Forbid all use of C++.";
  }

  // PRIVATE

  /**
  * Custom deserialization is needed.
  */
  private void readObject(
    ObjectInputStream stream
  ) throws IOException, ClassNotFoundException {
    stream.defaultReadObject();
    //manually deserialize and init superclass
    String winningParty = (String)stream.readObject();
    init(winningParty);
  }

  /**
  * Custom serialization is needed.
  */
  private void writeObject(ObjectOutputStream stream) throws IOException {
    stream.defaultWriteObject();
    //manually serialize superclass
    stream.writeObject(getWinningParty());
  }
} 

See Also :
Implementing Serializable
Designing for subclassing