JavaRush /Java блог /Архив info.javarush /Конструктор по умолчанию и сохранение целостности классов...
articles
15 уровень

Конструктор по умолчанию и сохранение целостности классов в Java

Статья из группы Архив info.javarush
При проектировании классов, предназначенных для наследования (например, абстрактных классов) считается хорошим тоном не реализовывать интерфейс 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
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ