ProgrammatieJava ontwikkelaar

Leg de verschillen uit tussen shallow copy en deep copy in Java. Hoe worden ze geïmplementeerd en wanneer kan de behoefte aan gebruik ontstaan?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

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:

  • Shallow copy is voldoende als de structuur van het object geen wijzigbare geneste objecten bevat, of als het niet nodig is om de geneste objecten te wijzigen.
  • Deep copy is noodzakelijk als de wijzigbaarheid van geneste objecten cruciaal is en eventuele aanpassingen aan de kopie niet moeten worden weerspiegeld in het origineel.

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)); } }

Vragende vraag

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.