Jetzt halte aber mal die Kopie flach! Von flachen und tiefen Kopien.
Hast du schon mal ein Objekt kopieren wollen und das neue ums Verrecken nicht abändern können, ohne dass sich das Original mit ändert? Dann bist du über eine flache Kopie gestolpert!
Ich bin über eine flache Kopie gestolpert! Über was denn für eine Kopie, äh? Na über die eines komplexen Objekts! … Bist du high?? …
Ein beliebtes Ärgernis – in der Welt der Programmierung – ist das richtige kopieren von Objekten.
So scheint es auf dem ersten Blick unlogisch, dass man eine selbst erstellte Klasse instanziiert, mit Werten bestückt, kopiert (Klasse objektNeu = objektAlt), die neue Instanz abändert und im alten Objekt genau dieselben – abgeänderten – Werte vorfindet.
Macht man dasselbe hingegen bei einem einfachen Integer Datenwert, lässt sich dieser problemlos kopieren, und man erhält anschließend zwei unterschiedliche Werte.
Primitive- und Komplexe-Objekte
Um diesem Phänomen auf die Schliche zu kommen muss man wissen, dass Java – wie auch die meisten anderen Programmiersprachen – zwischen komplexen und primitiven Objekten unterscheidet. Primitive Objekte sind die einfachen Datentypen wie Byte, Short, Integer, Long, Double, String. Diese lassen sich problemlos kopieren und unabhängig abändern.
Auf der anderen Seite stehen die komplexen Objekte, dazu zählen im Prinzip alle anderen Klassen, die wiederrum aus eigenen Methoden und Variablen – welche von primitiver Natur sind – bestehen. Diese lassen sich nicht so einfach kopieren. Hier kommen die flachen und tiefen Kopien ins Spiel.
Flache Kopie
Streng genommen kopiert man bei der flachen Kopie gar nicht. Im eigentlichen setzt man nur einen Verweis. So sagt man dem Programm lediglich, dass das neue Objekt einen Verweis auf das alte bekommt. Dabei sind die beiden Instanzen direkt miteinander verbunden. Ändert man einen Wert in der neuen Instanz, ändert sich dieser auch in der Alten und andersherum.
Flache Kopie: Ein Beispiel
Unser komplexes Objekt, ist eine selbst erstellte Koordinaten-Klasse. Ich habe die Getter und Setter der einfachhalber weggelassen.
/**
* Beschreibt eine Koordinate in x, y und z
*/
public class Koordinate {
/** x-Koordinate */
public int x;
/** y-Koordinate */
public int y;
/** z-Koordinate */
public int z;
/** Standardkonstruktor */
public Koordinate(int x, int y, int z) {
this.x = x;
this.y = y;
this.z = z;
}
/**
* gibt die Koordinate in Textform aus
* @return Kooridnaten als String
*/
public String getTextual() {
return "x: " + this.x + "y: " + this.y + "z: " + this.z;
}
}
Im nächsten Teil erstellen wir zwei Instanzen. Die Original-Koordinate beschreiben wir und geben sie aus. Anschließend wird diese flach in die Kopie-Koordinate kopiert. Jetzt ändern wir die Werte der Kopie-Koordinate und siehe da, in der Ausgabe können wir sehen, dass sich beide Werte geändert haben.
//erstellen von Original
Koordinate originalK = new Koordinate(1,2,3);
//Ausgabe vom Original
System.out.println("1: originalK - " + originalK.getTextual());
//flache kopie erstellen
Koordinate copyK = originalK;
//Ausgabe der flachen Kopie
System.out.println("2: copyK - " + copyK.getTextual());
//neue Werte für Kopie
copyK.x = 11;
copyK.y = 12;
copyK.z = 13;
//Ausgabe Original und Kopie
System.out.println("3: copyK - " + copyK.getTextual());
System.out.println("4: originalK - " + originalK.getTextual());
Ausgabe:
1: originalK - x: 1 y: 2 z: 3
2: copyK - x: 1 y: 2 z: 3
3: copyK - x: 11 y: 12 z: 13
4: originalK - x: 11 y: 12 z: 13
Die Object-ID nach Flacher Kopie
Ganz hilfreich ist dabei die Methode „.toString()“. Diese gibt mir, insofern sie nicht überschrieben wurde, die ID eines Objekts zurück. Dabei sehen wir, dass diese für beide gleich ist.
System.out.println("OriginalID: " + originalK.toString());
System.out.println("KopieID: " + copyK.toString());
Ausgabe:
OriginalID: Koordinate@e53108
KopieID: Koordinate@e53108
Danke für den tollen Artikel.