JavaRush /Blog Java /Random-FR /Constructeur par défaut et préservation de l'intégrité de...
articles
Niveau 15

Constructeur par défaut et préservation de l'intégrité de la classe en Java

Publié dans le groupe Random-FR
Lors de la conception de classes destinées à l'héritage (par exemple, des classes abstraites), il est considéré comme une bonne pratique de ne pas implémenter d'interface Serializableet de décider individuellement dans chaque classe descendante si elle doit être sérialisée ou non. Cependant, une telle classe doit avoir un constructeur par défaut pour que les mécanismes de sérialisation créent correctement l'objet. Et parfois, il n’existe aucun moyen de fournir un constructeur par défaut sans rompre l’intégrité de la classe. Constructeur par défaut et maintien de l'intégrité des classes en Java - 1Une telle classe doit souvent prendre comme paramètre un objet sans lequel elle ne peut pas fonctionner normalement, et fournir un constructeur par défaut violera l'intégrité de la classe. Dans une telle situation, vous pouvez fournir un constructeur, mais interdire de travailler avec lui jusqu'à ce qu'il soit complètement initialisé. Pour ce faire, vous pouvez introduire un état dans une classe, et autoriser l'appel de ses méthodes uniquement si l'état de cette classe est « initialisé ». Exemple tiré du livre "Java efficace" :

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);
    }
}
Dans le même temps, toutes les méthodes de cette classe doivent vérifier l'état actuel de la classe et empêcher son utilisation incorrecte, et les méthodes readObject()et doivent être définies dans la classe descendante writeObject(). Lien vers la source originale : http://0agr.ru
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION