Serialisierung - Standardwert für nachträglich hinzugefügtes Feld

Cola_Colin

Top Contributor
Hallo,

ich habe habe gerade zu einer Klasse, von der ich bereits ein paar dutzend Serialisierungen habe, ein Feld hinzufügen müssen(wollen). Sein Standardwert soll 1 sein, blöderweise wird es mit 0 geladenen, wen ich eine der alten Dateien öffne. Da 0 im Bereich des Möglichen für den Wert liegt, kann ich nicht einfach sagen "0 ist falsch, 1 rein".

Das einzige, was mir einfällt ist das:
Java:
    private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException {
        s.defaultReadObject();
        if (dummy == null) { // Ist das Dummyfeld null, so wird das eigentliche Feld 1 sein müssen.
            gravityFactor = 1;
        }
    }

    // Das eigentliche neue Feld
    private float gravityFactor = 1;
    // Dummyfeld, gab es in der alten Version auch nicht
    private Object dummy = new Object();

Gibt es eine Möglichkeit diesen Standardwert elegant auf 1 zu setzen ? Meine Lösung wirkt doch... wie ein sehr umständlicher Workaround.

EDIT: Und es funktioniert nichtmal, der Wert 1 wird nun scheinbar immer eingelesen.
 
Zuletzt bearbeitet:
Du könntest für den Faktor die Float-Klasse nehmen. Da gibt es dann den Untesrchied zwischen null und 0 und du sparst dir den Dummy.

Ich kenne ja jetzt nicht die ganze Klasse, aber evtl. könnte es sinnvoll sein das decorator pattern anzuwenden um die Daten/Zustande daran zu halten. Objekte dieser Art könenn auch leichter erweitert bzw. angepasst werden.
 
Die Klasse speichert ausschließlich Daten um sie zu serialisieren, sie besitzt keine Funktionslogik.

Java:
// javaDoc 29.August
package gameDefinitions;

import java.awt.geom.Point2D;
import java.awt.geom.Point2D.Float;
import java.io.Serializable;
import java.lang.reflect.Field;

/**
 * Klasse bietet alle Infos, die für das erstellen eines {@link sprite.Sprite} nötig sind.<p>
 * Wird verwendet um per deserialisierung speicher und ladbare Levels zu erhalten.<p>
 * @author Colin Clausen
 */
public class SpriteDef implements Serializable, Cloneable {

    private static final long serialVersionUID = 5131138227391889114L;

    /**
     * Erstellt einen clone, der alle Felder, die nicht primitiv sind und Cloneable implementieren,
     * ebenfalls mit deren clone() cloned. <p>
     * Bei zirkulären Referenzen solcher Felder endet das vermutlich in einer Endlosschleife ?!
     * <p> Solche Referenzen dürfen nicht vorkommen.
     */
    @Override // Im Endeffekt ist das sicherlich inzwischen auch einfacher zu lösen. War mal so nötig. Da es so jedoch einfacher zu erweitern ist, lasse ich es so.
    public SpriteDef clone() {
        try {
            SpriteDef tmp = (SpriteDef) super.clone(); // Zuerst das Object normal clonen
            for (Class<?> c = tmp.getClass(); c != null; c = c.getSuperclass()) { // jetzt alle Felder durchlaufen
                Field[] declaredFields = c.getDeclaredFields();
                Field.setAccessible(declaredFields, true); // auf alle Felder zugreifen
                for (Field f : declaredFields) {
                    interfacesearch: // suche nach dem Interface Cloneable bei alle Feldern,
                    if (!f.getType().isPrimitive()) { // die nicht primitiv sind
                        for (Class<?> tClass = f.getType(); tClass != null; tClass = tClass.getSuperclass()) {
                            Class<?>[] interfaces = tClass.getInterfaces();
                            for (Class<?> aC : interfaces) {
                                if (aC.equals(Cloneable.class)) {
                                    try { // wenn Interface gefunden, also das Feld cloneable ist, dann clone es.
                                        f.set(tmp, tClass.getMethod("clone", (Class<?>[]) null).invoke(f.get(tmp), (Object[]) null));
                                        break interfacesearch;
                                    } catch (Exception ex) {
                                        ex.printStackTrace();
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return tmp;
        } catch (CloneNotSupportedException e) {
            throw new Error(e); // Wenn das passiert ist irgendwas ganz ganz schief gewickelt.
        }
    }

    /** Name */
    String name = "Sample";
    /** Position */
    Point2D.Float position = new Point2D.Float(0, 0);
    /** Rotationsausrichtung im Bogenmaß*/
    float angle = 0;
    /** Z Koordinate des Körpers (layer) */
    int z = 0;
    /** Soll die Rotation des Körpers gefixed werden ?*/
    boolean fixAngle = false;
    /** Größe */
    Point2D.Float size = new Point2D.Float(10, 10);
    /** Texturename */
    String textureName = "";
    /** Animationsstart */
    int animStart = 1;
    /** AnimationsEnde */
    int animEnd = 1;
    /** Animationszustand, ist animEnabled == false oder animStart == animEnd, so bleibt es auch bei diesem */
    int animState = 1;
    /** Geschwindigkeit der Animation in Bildern pro Sekunde */
    float animSpeed = 1;
    /** Name Shape */
    String shapeName = null;
    /** Restitution des Shapes */
    float restituion = 0;
    /** Friction des Shapes */
    float friction = 1;
    /** Dichte des Shapes */
    float density = 1;
    /** Angabe, ob das Shape ein Sensor ist. Ein Sensor erzeugt keine Kollisionsantworten, führt jedoch zu Collisionevents */
    boolean isSensor = false;
    /** Dämpfung, die auf Bewegungen des Sprites wirkt */
    float damping = 0;

    /** Script File für dieses Shape */
    String script = "static";
    /** Settingsfile für dieses Shape */
    String scriptSettings = "none";

    public boolean isSensor() {
        return isSensor;
    }

    public String getScript() {
        return script;
    }

    public String getScriptSettings() {
        return scriptSettings;
    }

    public String getName() {
        return name;
    }

    public float getDamping() {
        return damping;
    }

    public float getDensity() {
        return density;
    }

    public float getFriction() {
        return friction;
    }

    public float getRestituion() {
        return restituion;
    }

    public String getShapeName() {
        return shapeName;
    }

    public float getAnimSpeed() {
        return animSpeed;
    }

    public int getAnimState() {
        return animState;
    }

    public int getAnimEnd() {
        return animEnd;
    }

    public int getAnimStart() {
        return animStart;
    }

    public String getTextureName() {
        return textureName;
    }

    public Point2D.Float getSize() {
        return (Float) size.clone();
    }

    public boolean isFixedAngle() {
        return fixAngle;
    }

    public int getZ() {
        return z;
    }

    public float getAngle() {
        return angle;
    }

    public Point2D.Float getPosition() {
        return (Float) position.clone();
    }

    public void setName(String name) {
        this.name = name;
    }

    public void setPosition(Point2D.Float position) {
        this.position = position;
    }

    public void setPosition(float x, float y) {
        this.position = new Point2D.Float(x, y);
    }

    public void setAngle(float angle) {
        this.angle = angle;
    }

    public void setZ(int z) {
        this.z = z;
    }

    public void setFixAngle(boolean fixAngle) {
        this.fixAngle = fixAngle;
    }

    public void setSize(Point2D.Float size) {
        this.size = size;
    }

    public void setTextureName(String textureName) {
        this.textureName = textureName;
    }

    public void setAnimStart(int animStart) {
        this.animStart = animStart;
    }

    public void setAnimEnd(int animEnd) {
        this.animEnd = animEnd;
    }

    public void setAnimState(int animState) {
        this.animState = animState;
    }

    public void setAnimSpeed(float animSpeed) {
        this.animSpeed = animSpeed;
    }

    public void setShapeName(String shapeName) {
        this.shapeName = shapeName;
    }

    public void setRestituion(float restituion) {
        this.restituion = restituion;
    }

    public void setFriction(float friction) {
        this.friction = friction;
    }

    public void setDensity(float density) {
        this.density = density;
    }

    public void setIsSensor(boolean isSensor) {
        this.isSensor = isSensor;
    }

    public void setDamping(float damping) {
        this.damping = damping;
    }

    public void setScript(String script) {
        this.script = script;
    }

    public void setScriptSettings(String scriptSettings) {
        this.scriptSettings = scriptSettings;
    }
}

Decorator bringen da wenig, oder ? Von der Beschreibung auf wiki her, sind ja z.B. die ganzen Streams nach dem Konzept geschrieben ? Pattern kenne ich nicht soviele 😳

Ich probiere mal ein Float Objekt.

Danke für die Tipps.
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben