JavaRush /Java Blog /Random-IT /Costruttore predefinito e preservazione dell'integrità de...
articles
Livello 15

Costruttore predefinito e preservazione dell'integrità della classe in Java

Pubblicato nel gruppo Random-IT
Quando si progettano classi destinate all'ereditarietà (ad esempio, classi astratte), è considerata buona pratica non implementare un'interfaccia Serializablee decidere individualmente in ciascuna classe discendente se necessita di essere serializzata o meno. Tuttavia, tale classe deve avere un costruttore predefinito affinché i meccanismi di serializzazione possano creare correttamente l'oggetto. E a volte non è possibile fornire un costruttore predefinito senza compromettere l'integrità della classe. Costruttore predefinito e mantenimento dell'integrità della classe in Java - 1Una classe di questo tipo spesso deve prendere come parametro qualche oggetto senza il quale non può funzionare normalmente, e fornire un costruttore predefinito violerà l'integrità della classe. In una situazione del genere, è possibile fornire un costruttore, ma vietare di lavorarci fino a quando non sarà completamente inizializzato. Per fare ciò, puoi introdurre uno stato in una classe e consentire la chiamata dei suoi metodi solo se lo stato di questa classe è "inizializzato". Esempio dal libro "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);
    }
}
Allo stesso tempo, tutti i metodi di questa classe devono verificare lo stato attuale della classe e impedirne l'uso errato, e i metodi readObject()e devono essere definiti nella classe discendente writeObject(). Link alla fonte originale: http://0agr.ru
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION