In Java ist shallow copy (flaches Kopieren) eine Kopie eines Objekts, bei der nur die Referenzen auf die enthaltenen Objekte kopiert werden, nicht die Objekte selbst. Änderungen an den enthaltenen Objekten spiegeln sich sowohl in der Kopie als auch im Original wider. Deep copy (tiefes Kopieren) bedeutet, dass neue unabhängige Kopien aller enthaltenen Objekte erstellt werden.
class Address implements Cloneable { String city; Address(String city) { this.city = city; } protected Object clone() throws CloneNotSupportedException { return super.clone(); } } class Person implements Cloneable { String name; Address address; Person(String name, Address address) { this.name = name; this.address = address; } protected Object clone() throws CloneNotSupportedException { return super.clone(); } } // Verwendung Person p1 = new Person("Ivan", new Address("Moscow")); Person p2 = (Person) p1.clone(); p2.address.city = "Petersburg"; System.out.println(p1.address.city); // Gibt "Petersburg" aus - flaches Kopieren
class Address implements Cloneable { String city; Address(String city) { this.city = city; } protected Object clone() throws CloneNotSupportedException { return new Address(this.city); } } class Person implements Cloneable { String name; Address address; Person(String name, Address address) { this.name = name; this.address = address; } protected Object clone() throws CloneNotSupportedException { Person cloned = (Person) super.clone(); cloned.address = (Address) address.clone(); return cloned; } }
Das tiefe Kopieren ermöglicht es, eine vollständig unabhängige Kopie eines Objekts zu erstellen.
Frage: Kann die Methode clone() für eine garantierte tiefe Kopie eines beliebigen komplexen Objekts verwendet werden?
Antwort: Nein, die Standardmethoden clone() machen nur flaches Kopieren (shallow copy). Für ein tiefes Kopieren muss clone() in allen enthaltenen Klassen überschrieben und alle Referenzfelder explizit geklont werden. Außerdem unterstützen viele Sammlungen und Standardklassen kein tiefes Klonen.
Geschichte
Die Sammlung von Benutzern und deren Adressen wurde mit der Methode clone() ohne tiefes Kopieren geklont. Nach der Änderung der Adresse eines Benutzers änderte sich die Adresse eines anderen, weil die Referenz kopiert wurde. Die Daten in der Datenbank "flossen" zwischen den Benutzern.
Geschichte
Beim Serialisieren eines komplexen Objekts mit enthaltenen Sammlungen wurde clone() anstelle einer tiefen Kopie verwendet. Nach der Wiederherstellung aus der Serialisierung waren die Daten inkonsistent und es gab NPEs.
Geschichte
In der REST API wurden DTO-Objekte standardmäßig über BeanUtils.copyProperties() geklont, was zu einer Teilung derselben Sammlung zwischen den Clients führte. Infolgedessen konnte ein Benutzer die Daten anderer sehen und bearbeiten.