JavaRush /Java Blog /Random-TW /Java 中的預設建構函式和保持類別完整性
articles
等級 15

Java 中的預設建構函式和保持類別完整性

在 Random-TW 群組發布
在設計用於繼承的類別(例如抽象類別)時,最好不要實作接口Serializable,並在每個後代類別中單獨決定是否需要序列化。但是,這樣的類別必須具有預設建構函數,以便序列化機制正確建立物件。有時,無法在不破壞類別完整性的情況下提供預設建構子。 Java 中的預設建構函式和維護類別完整性 - 1這樣的類別通常必須採用某個物件作為參數,否則它無法正常運行,並且提供預設建構子將違反類別的完整性。在這種情況下,您可以提供一個建構函數,但在它完全初始化之前禁止使用它。為此,您可以在類別中引入一個狀態,並允許僅當該類別的狀態為「初始化」時才呼叫其方法。《Effective java》一書中的範例:
public abstract class AbstractFoo {
    private int x, y;

    private enum State {
        NEW, INITIALIZING, INITIALIZED
    };

    private final AtomicReference<State> init = new AtomicReference<State>(State.NEW);

    protected AbstractFoo() {}

    public AbstractFoo(int x, int y) {
        initialize(x, y);
    }

    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;
        init.set(State.INITIALIZED);
    }

    protected final int getX() {
        checkInit();
        return x;
    }

    protected final int getY() {
        checkInit();
        return y;
    }

    private void checkInit() {
        if (init.get() != State.INITIALIZED) {
            throw new IllegalStateException("Uninitialized");
        }
    }
}

class Foo extends AbstractFoo implements Serializable {
    private void readObject(ObjectInputStream s) throws IOException,
            ClassNotFoundException {
        s.defaultReadObject();
        int x = s.readInt();
        int y = s.readInt();
        initialize(x, y);
    }

    private void writeObject(ObjectOutputStream s) throws IOException {
        s.defaultWriteObject();
        s.writeInt(getX());
        s.writeInt(getY());
    }

    public Foo(int x, int y) {
        super(x, y);
    }
}
同時,該類別的所有方法都必須檢查該類別的當前狀態並防止其錯誤使用,並且方法readObject()和必須在後代類別中定義writeObject()。原始來源連結: http: //0agr.ru
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION