Shallow copy (oppervlakkige kopie) creëert een nieuw object, maar kopieert alleen de referenties naar geneste objecten in plaats van de objecten zelf. Deep copy (diepe kopie) creëert een nieuw object en kopieert recursief alle objecten die genest zijn in het origineel, zodat er geen gemeenschappelijke referenties tussen de kopie en het origineel zijn.
Wanneer te gebruiken:
Voorbeeldimplementatie:
// Voorbeeld van een klasse met een genest object 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)); } }
Kan deep copy worden geïmplementeerd met de clone()-methode?
Antwoord:
Nee, de standaardmethode Object.clone() implementeert alleen "shallow copy". Om deep copy te verkrijgen, moet men ofwel handmatig alle geneste velden klonen, of externe bibliotheken gebruiken (bijvoorbeeld Apache Commons Lang).
Voorbeeld:
@Override public Person clone() throws CloneNotSupportedException { Person cloned = (Person) super.clone(); cloned.address = new Address(this.address.city); // deep copy handmatig return cloned; }
Geschiedenis
In een groot CRM-project, na de implementatie van het klonen van objecten via
super.clone(), verwachtte de ontwikkelaar volledige onafhankelijkheid van de kopieën, maar bij het wijzigen van het adres van de gekloonde gebruiker veranderde ook het adres van het origineel. De bug werd pas na de release vastgesteld en veroorzaakte verwarring in de klantenbasis.
Geschiedenis
Bij serialisatie/deserialisatie voor diepe kopieën werd het standaard mechanisme Serializable gekozen. Echter, men vergat een van de velden van het geneste object als Serializable te declareren, wat leidde tot fouten tijdens het draaien (NotSerializableException) en dataverlies bij het maken van back-ups.
Geschiedenis
In een van de microservices werd de BeanUtils.copyProperties-bibliotheek gebruikt voor het kopiëren van DTO's, zonder te beseffen dat het mechanisme alleen shallow copy implementeert. Na de refactoring ontstonden er veel onduidelijke bugs, waarbij wijzigingen in geneste collecties invloed hadden op de originele gegevens die uit de database waren verkregen.