JavaRush /Blog Java /Random-PL /Konstruktor domyślny i zachowanie integralności klas w Ja...
articles
Poziom 15

Konstruktor domyślny i zachowanie integralności klas w Javie

Opublikowano w grupie Random-PL
Projektując klasy przeznaczone do dziedziczenia (na przykład klasy abstrakcyjne), za dobrą praktykę uważa się nie implementowanie interfejsu Serializablei samodzielne podejmowanie decyzji w każdej klasie potomnej, czy wymaga ona serializacji, czy nie. Jednak taka klasa musi mieć konstruktor domyślny, aby mechanizmy serializacji poprawnie utworzyły obiekt. Czasami nie ma możliwości zapewnienia domyślnego konstruktora bez naruszenia integralności klasy. Domyślny konstruktor i utrzymanie integralności klasy w Javie - 1Taka klasa często musi przyjmować jako parametr jakiś obiekt, bez którego nie może normalnie funkcjonować, a podanie domyślnego konstruktora naruszy integralność klasy. W takiej sytuacji możesz udostępnić konstruktor, ale zabronić z nim pracy do czasu jego pełnej inicjalizacji. Aby to zrobić, możesz wprowadzić stan do klasy i zezwolić na wywoływanie jej metod tylko wtedy, gdy stan tej klasy jest „zainicjowany”. Przykład z książki „Efektywna 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);
    }
}
Jednocześnie wszystkie metody tej klasy muszą sprawdzać aktualny stan klasy i zapobiegać jej nieprawidłowemu użyciu, a metody readObject()i muszą być zdefiniowane w klasie potomnej writeObject(). Link do oryginalnego źródła: http://0agr.ru
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION