Implementing Serializable
Designing for subclassing
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()); } }