4.11.2 | Kopieren von Objekten |
Beim Kopieren von Objekten sind grundsätzlich zwei verschiedene Semantiken zu unterscheiden:
- Flaches Kopieren, d. h., es wird eine bitweise Kopie des Objekts erstellt, Referenzen auf andere Objekte bleiben dabei erhalten.
- Tiefes Kopieren, d. h., zusätzlich werden rekursiv Kopien von den referenzierten Objekten erzeugt.
Das Kopieren von Objekten muss sorgfältig vom Kopieren einer Referenz auf ein Objekt unterschieden werden, das im vorhergehenden Abschnitt behandelt wurde.
Für das flache Kopieren stellt Java einen Mechanismus bereit, der aus dem Interface java.lang.Cloneable und aus der Methode clone() der Klasse Object besteht. Diese Methode erzeugt eine identische Kopie des aufgerufenen Objekts und liefert sie zurück.
Dadurch, dass clone() in Object definiert ist, steht sie in allen Klassen und auch für Arrays zur Verfügung.
Die Voraussetzung für das Kopieren mit clone() ist, dass die betreffende Klasse das Interface Cloneable implementiert. Bei Cloneable handelt es sich um ein Flag-Interface, es ist leer und dient lediglich dazu, anzuzeigen, dass eine Klasse das Kopieren zuläßt.
Falls clone() auf ein Objekt angewendet wird, dessen Klasse dieses Interface nicht implementiert, wird eine CloneNotSupportedException ausgelöst. Bei der Verwendung von clone() muss beachtet werden, dass diese Methode in Object als protected vereinbart ist und somit nur aus der Klasse selbst heraus aufgerufen werden kann.
Im folgenden Beispiel wird clone() als public redeklariert, wodurch sie auch von »außen« aufgerufen werden kann:public class Buffer implements Cloneable { int[] buffer = new int[100]; ... public Object clone() { Object theClone = null; try { theClone = super.clone(); } catch(CloneNotSupportedException e) { } return theClone; } }Weiterhin muss die CloneNotSupportedException beim Aufruf von Object.clone() abgefangen werden, auch wenn sie wie im Beispiel nie auftreten kann, da die Klasse, aus der die Methode aufgerufen wird, Cloneable implementiert.
In Abschnitt 2.15.6 wird gezeigt, wie clone() zum Kopieren von Arrays benutzt wird.
Standardmäßig bietet Java keine direkte Möglichkeit zum tiefen Kopieren. Man kann sich aber der in Java 1.1 eingeführten Serialisierung bedienen, um einen Objektgraph rekursiv zu kopieren.
Der Kopiervorgang hat prinzipiell folgenden Ablauf:
- Zunächst wird das zu kopierende Objekt einschließlich aller rekursiv erreichbaren Objekte abgespeichert, z. B. in einem byte-Array oder einer Datei.
- Anschließend wird der gespeicherte Objektgraph wieder eingelesen. Beim Einlesen werden anhand der gespeicherten Daten neue Objekte erzeugt, wodurch der Graph insgesamt kopiert wird.
Das Schreiben und Einlesen erfolgt unter Verwendung der in Java 1.1 eingeführten Objekt-Streams, die in Abschnitt 10.4.2 vorgestellt werden. Dort befindet sich auch ein Beispiel zum tiefen Kopieren.