JavaRush /Java блог /Random UA /Конструктор за замовчуванням та збереження цілісності кла...
articles
15 рівень

Конструктор за замовчуванням та збереження цілісності класів у Java

Стаття з групи Random UA
При проектуванні класів, призначених для успадкування (наприклад, абстрактних класів) вважається хорошим тоном не реалізовувати інтерфейс 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
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ