非シリアライズ可能な拡張可能クラスへのパラメータなしコンストラクタのaddidでは特別な点は何ですか?非シリアライズ可能な拡張可能クラスへのパラメータのないコンストラクタの追加
有効なjavaでは、このトピックについて著者が話します。単純にその残りのコンストラクタその 不変量を確立エラーの可能性を増加させる、状態空間が複雑になるクラスにパラメータなしのコンストラクタと 別個の初期化メソッドを追加
。
次のコードは、効果的なJavaの第2版[ページ292-293]
public 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
}
からコピーされAbstractFooのすべてのパブリックおよび保護されたインスタンスメソッドは、何かを行う前に でcheckinitを呼び出す必要があります。こうすることで、記述されていないサブクラスがインスタンスの初期化に失敗した場合、メソッドの呼び出しに が素早くきれいに失敗することが保証されます。注釈 は、初期化されたフィールドが原子参照(java.util.concurrent。 atomic.AtomicReference)であることを示します。これは、確定した敵の顔に のオブジェクトの完全性を保証するために必要です。この予防措置が存在しない場合、あるスレッドが を使用しようとしている間に、あるスレッドがインスタンスに対してinitializeを呼び出すと、2番目のスレッドがそのインスタンスを矛盾した状態にすることがあります。
なぜこれを行うのですか?私はこれを完全に理解していませんでした。誰でも説明できますか?