Objekt kopieren

Hi,
Ich würde gerne ein Objekt kopieren. So wie man eine Elementar Variable kopiert.
Code schnipsel
Tester test = new Tester();
test.t1 = 101;
test.t2 = …

Wenn ich jetzt :
Tester testCopy = test;
mache, erstelle ich eine zweite Referenz auf das selbe Objekt. (wenn ich richtig bin)
Selbst wenn ich
Tester testCopy = new Tester();
testCopy = test;

Erstelle ich nur eine zweite Referenz auf das selbe Objekt.
Das heißt egal ob ich test.t1 ändere oder testCopy.t1 ändere es ist dasselbe.

Ich würde aber gerne das gesamte Objekt kopieren mit allen Instanzen.
Geht das? Ohne dass ich
testCopy.t1 = test.t1;
testCopy.t2 = test.t2;

mache? (Alle Instanzen einzel kopiere)

Habe ich mich klar ausgedrückt?
Danke für Eure Hilfe

Grüße
Winter

Hallo!

Habe ich mich klar ausgedrückt?

Glasklar.
4 Möglichkeiten:

  • clone()
  • Copy-Constructor
  • Factory-Methode
  • Serialisierung/Deserialiserung

Danke für Eure Hilfe

Ich hoffe, die Begriffe reichen (erstmal)? Das, was du zu clone() findest, wird dich vermutlich auch zu den genannten Alternativen führen. Da spare ich mir erstmal viel Worte.

Gruß, Jan

Hallo JayVee,
danke für Deine fixe Antwort.
Muss mich noch genau reinlesen wie das Clone funktioniert, aber das ist ja auch den Sinn an der Sache Hilfe zur Selbsthilfe.
Vielen Dank!
Winter

tiefes und flaches Kopieren mit clone()
Am besten geht das mit der Clone-Methode. Es gibt zwei Möglichkeiten.

Flache Kopie
Du erstellst ein neues Objekt der zuklonenden Klasse.
Du kopierst alle Variablen (auch Objektrefernzen).

Object clone(){
 A result = new result();
 result.int1 = this.int1;
 result.object1 = this.object1;
}

Tiefe Kopie
Du kopierst nur Variablen der Grunddatentypen (int, double, boolean, …).
Statt Objektreferenzen zu kopieren, führst du clone() für alle referenzierten Objekte aus:

@Override
Object clone(){
 A result = new result();
 result.int1 = this.int1;
 result.object1 = this.object1.clone();
}

Im obrigen Fall muss in der Klasse von object1 die Clone-Methode überschrieben worden sein. So werden alle Klasse rekursiv geklont.

Was ist der Unterschied?
Bei einer tiefen Kopie, sind alle referenzierten Objekte ebenfalls kopiert worden.
Bei einer flachen Kopie zeigt der Pointer von kopierter und von der orginal Klasse auf das selbe Objekt.
Beispiel:

Auto auto = new Auto();
auto.setMotor(new Motor());
auto.getMotor().setPS(75);
Auto getuntesAuto = auto.clone();
getuntesAuto.getMotor().setPS(250);

getuntesAuto.printPower(); //Ausgabe: 250PS
auto.printPower(); //Ausgabe: "250PS" bei einer flachen Kopie, "75PS" bei einer tiefen Kopie.

Bei einer flachen Kopie hätten beide Autos den selben Motor (selbes Objekt). Verändert man also die PS-Zahl am getunten Auto, wird auch das normale Auto verändert. Bei einer tiefen Kopie hätte jedes Auto sein eigenes Motorobjekt. Eine PS-Änderung hätte also auch nur auf ein Auto einen Efekt.

Aber auch eine flache Kopie, hat durchaus ihren Sinn. Stellt euch die Klasse Fussgaenger vor, die ein Objekt der Klasse Stadt in der Variable aufenthalts_ort hat.
Hier wäre eine flache Kopie sinnvoll. Zwei Fußgänger können ja in der selben Stadt flanieren, aber nicht in der Kopie einer Stadt :smile:

Vorsicht bei clone()!
Die clone() Kopiererei hat aber auch diverse Nachteile, die insbesondere auf die tiefe Kopie zutreffen. Denn wenn andere Objekte eine Referenz aufeinander halten, dann ist das Objekt nach dem Kopieren „kaputt“, da die referentielle Integrität dadurch u.U. zerstört wurde.

Beispiel:
Eine Person, die eine Liste mit Adressen hat. Eine von diesen ist als Hauptadresse gesetzt, d.h. die Referenz in der Adress-Liste und die Referenz der Hauptadresse beziehen sich auf dasselbe Objekt.

Person1

  • adressen [Adresse1, Adresse2 , Adresse3]
  • hauptadresse: Adresse2

Wenn ich nun eine Tiefen-Kopie mache, in der alle Objekte kopiert werden erhalte ich:

Person1a

  • adressen [Adresse1a, Adresse2a , Adresse3a]
  • hauptadresse: Adresse2b

Nun zeigt eben die Hauptadresse nicht mehr auf ein Objekt der Adress-Liste. Ändere ich nun z.B. die Strasse von Adresse2a in der Adress-Liste, dann beinhaltet die Hauptadresse noch die alte falsche Information, weil das ja jetzt ein anderes Objekt (Adresse2b) ist.

Fazit:
Das Klonen von Objekten kann zu Inkonsistenzen führen, die später irgendwo zu Fehlern führen. Wenn man Objekte klont, sollte man sich wirklich vergewissern, dass man von diesen Objekten nicht betroffen ist.

Die einzige mir bekannte konsistente Art Objekte zu kopieren (ohne die referenzielle Integrität des Objektes zu zerstören) sind die Serialisierung/Deserialisierung von Objekten mit geeigneten Frameworks wie XStream. Dort verweist nach der Kopie die Hauptadresse immer noch auf eine Adresse aus der Adress-Liste. Die Integrität ist also nicht verletzt worden.