ProgrammierungJava Entwickler

Erklären Sie die Unterschiede zwischen shallow copy und deep copy in Java. Wie werden sie implementiert und wann kann die Notwendigkeit ihrer Verwendung auftreten?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort

Shallow copy (flaches Kopieren) erstellt ein neues Objekt, kopiert jedoch nur die Referenzen auf die eingebetteten Objekte und nicht die Objekte selbst. Deep copy (tiefes Kopieren) erstellt ein neues Objekt und kopiert rekursiv alle Objekte, die in das ursprüngliche eingebettet sind, sodass zwischen der Kopie und dem Original keine gemeinsamen Referenzen bestehen.

Wann verwenden:

  • Shallow copy ist ausreichend, wenn die Objektstruktur keine veränderbaren eingebetteten Objekte enthält oder wenn eine Änderung der eingebetteten Objekte nicht erforderlich ist.
  • Deep copy ist notwendig, wenn die Änderbarkeit der eingebetteten Objekte kritisch ist und Änderungen an der Kopie nicht im Original reflektiert werden dürfen.

Beispielimplementation:

// Beispiel einer Klasse mit einem eingebetteten Objekt class Address { String city; Address(String city) { this.city = city; } } class Person implements Cloneable { String name; Address address; Person(String name, Address address) { this.name = name; this.address = address; } // Shallow copy public Person clone() throws CloneNotSupportedException { return (Person) super.clone(); } // Deep copy public Person deepClone() { return new Person(this.name, new Address(this.address.city)); } }

Trickfrage

Kann man deep copy mit der Methode clone() implementieren?

Antwort: Nein, die Standardmethode Object.clone() implementiert nur "shallow copy". Um deep copy zu erhalten, muss man entweder alle eingebetteten Felder manuell klonen oder externe Bibliotheken (z.B. Apache Commons Lang) verwenden.

Beispiel:

@Override public Person clone() throws CloneNotSupportedException { Person cloned = (Person) super.clone(); cloned.address = new Address(this.address.city); // manuelles deep copy return cloned; }

Geschichte

In einem großen CRM-Projekt erwartete der Entwickler nach der Implementierung des Kopierens von Objekten über super.clone(), dass die Kopien völlig unabhängig wären, aber als die Adresse des kopierten Benutzers geändert wurde, änderte sich auch die Adresse des Originals. Der Bug wurde erst nach dem Release entdeckt und führte zu Verwirrung in der Kundendatenbank.


Geschichte

Bei der Serialisierung/Deserialisierung wurde für das tiefe Kopieren der Standardmechanismus Serializable gewählt. Es wurde jedoch vergessen, eines der Felder des eingebetteten Objekts als Serializable zu deklarieren, was zu Fehlern während des Betriebs (NotSerializableException) und Datenverlusten bei Backups führte.


Geschichte

In einem der Mikrodienste wurde die Bibliothek BeanUtils.copyProperties zum Kopieren von DTO verwendet, ohne sich darüber im Klaren zu sein, dass der Mechanismus nur shallow copy implementiert. Nach der Refaktorisierung traten viele unauffällige Bugs auf, bei denen Änderungen an eingebetteten Sammlungen die Originaldaten, die aus der Datenbank abgefragt wurden, beeinflussten.