Zeigerproblematik

Hayo,
ich habe mir ein Objekt erstellt, mit dem Attribut pos. Pos enthält eine x und eine y Komponente. Am Anfang eines Rechenzyklus hole ich mir die Position aus dem Objekt via

Position pos = Objekt.getPos();
dann rechne ich damit weiter, aber ich habe das Gefühl, dass eine Änderung von pos auch eine Änderung des pos-Attributes von Objekt die Folge hat. Wie kann ich das umgehen? Bei ArrayLists würde ich jetzt die .clone() Methode aufrufen, aber das geht hier nicht ?_?

Position pos = Object.getPos();
// einige Methoden
if (irgendwas == true)
{
    Object.setPos(pos);
}
else
{
   //Object.pos wird nicht überschrieben
}

so war es von mir gedacht, aber ich habe bemerkt, dass sich wie gesagt alle Änderungen von pos auch sogleich auf Object.pos auswirken - wahrscheinlich verweist ein Zeiger auf das Objekt-Attribut

gerade habe ich eine Möglichkeit gefunden, die mir aber nicht gefällt:

Position pos = new Position(Object.getPos().getX(), Object.getPos().getY());
// einige Methoden
if (irgendwas == true)
{
    Object.setPos(pos);
}
else
{
   //Object.pos wird nicht überschrieben
}

geht das nicht noch intuitiver?

wenn x und y wiederum kein primitive sind und du einfach deren referenz weitergibst so haben aenderungen dann in den code abschnitten auswirkungen auf das eigentliche objekt.

am sichersten ist es als immutable das zu machen (wenn es das objekt erlaubt, keine ahnung wie dein Position objekt aussieht)

als statt

    return x;
}

dann

    return new Position(x); // oder new Position(x.wasAuchImmerXAusMacht);
    // copy konstruktor
}

genaues kann man eher sagen wenn du die Position klasse mal zeigst

ah ya, das würde gehen
meine Klasse ist total simpel. Ich hätte genauso auch das Objekt Dimension von awt zweckentfremden können.

class Position {
    private int x;
    private int y;

    public Position(int x, int y)
    {
         this.x = x; this.y = y;
    }

public int getX() {...}
public void setX(int x) {...}
// die anderen Getter-/ und Settermethoden
}

dein Weg ist sehr einleuchtend. Aber gefällt mir noch immer nicht so recht. Die Getter und Setter lasse ich mir automatisch erzeugen, es ist nicht die Idee dahinter, das dann im Nachhinein zu modifizieren. >_>

Alternativer Vorschlag: einfach Clonable implementieren und die clone Methode benutzen wie beim Array. Halte ich besonders bei größeren Klassen (Objekten) für besser (ist außerdem auch transparenter).

http://java.sun.com/javase/6/docs/api/java/lang/Cloneable.html

Ich finde, das “Cloneable” interface ist ziemlich … :twisted: naja… nicht so schön. Für solche Fälle gefällt mir ein Copy-Konstruktor besser


class Position
{
    private int x;
    private int y;

    public Position(int x, int y) 
    {
        this.x = x;
        thiy.y = y;
    }

    // Copy constructor
    public Position(Position that)
    {
        this(that.x, that.y);
    }
}

Hängt aber wohl auch vom Anwendungsfall ab.

sehr schön, vielen Dank, das hilft mir schonmal weiter

Schönheit ist sicherlich Geschmacksache :wink: , aber wenn man beispielsweise die Klassen später weiter verwenden möchte bzw. die Library weitergibt, hilft einem nur ein Interface weiter, denn dann kann der andere Programmierer schon anhand der Schnittstelle sehen, dass er das Objekt kopieren kann (implements Cloneable). Was genau im Konstruktor bzw. irgendwelchen anderen Methoden passiert sieht man nämlich nicht, es sei denn man schaut sich die Sourcen an (okay ich gebe zu bei einem Copy Konstruktor kann man sich das anhand des Parameters denken…). Hinzu kommt aber noch, dass der Konstruktor vielleicht Parameter besitzt, bzw. um solche erweitert werden muss. Das kann bei einem Clone-Konstruktor zu Problemen führen, da diese Parameter je nach Anwendungsfall nicht immer zur Verfügung stehen.

Ne andere Möglichkeit wäre noch die Serialisierung. Da wird ja auch ne Kopie erstellt. Ist aber langsamer.

Oder was ganz böses über Reflection :smiley: