// Nonserializable stateful class allowing serializable subclass - Pages 292-293 package org.effectivejava.examples.chapter11.item74; import java.util.concurrent.atomic.AtomicReference; public abstract class AbstractFoo { private int x, y; // Our state // This enum and field are used to track initialization private enum State { NEW, INITIALIZING, INITIALIZED }; private final AtomicReference<State> init = new AtomicReference<State>( State.NEW); public AbstractFoo(int x, int y) { initialize(x, y); } // This constructor and the following method allow // subclass's readObject method to initialize our state. protected AbstractFoo() { } protected final void initialize(int x, int y) { if (!init.compareAndSet(State.NEW, State.INITIALIZING)) throw new IllegalStateException("Already initialized"); this.x = x; this.y = y; // Do anything else the original constructor did init.set(State.INITIALIZED); } // These methods provide access to internal state so it can // be manually serialized by subclass's writeObject method. protected final int getX() { checkInit(); return x; } protected final int getY() { checkInit(); return y; } // Must call from all public and protected instance methods private void checkInit() { if (init.get() != State.INITIALIZED) throw new IllegalStateException("Uninitialized"); } // Remainder omitted }