In dit artikel van mijn gratis Java 8 cursus zal ik het verschil bespreken tussen een diepe en een ondiepe kopie. U kunt de dia ‘ s en het artikel hier als PDF downloaden.
Wat Is een kopie?
om te beginnen wil ik benadrukken wat een kopie in Java is. Laten we eerst een onderscheid maken tussen een referentiekopie en een objectkopie. Een referentiekopie, zoals de naam al aangeeft, maakt een kopie van een referentievariabele die naar een object wijst., Als we een auto-object hebben, met een MyCar-variabele die ernaar wijst en we maken een referentie-kopie, dan hebben we nu twee MyCar-variabelen, maar nog steeds één object.
Voorbeeld 1
een objectkopie maakt een kopie van het object zelf. Dus als we ons Auto-object opnieuw zouden kopiëren, zouden we een kopie van het object zelf maken, evenals een tweede referentievariabele die verwijst naar dat gekopieerde object.
Voorbeeld 2
Wat Is een Object?,
zowel een diepe kopie als een ondiepe kopie zijn typen objectkopieën, maar wat is echt een object? Vaak, als we over een object praten, spreken we over het als een enkele eenheid die niet verder kan worden afgebroken, zoals een nederige koffieboon. Maar dat is te simpel.
Voorbeeld 3
stel dat we een persoon object hebben. Ons Persoonsobject is in feite samengesteld uit andere objecten, zoals u kunt zien in Voorbeeld 4. Onze persoon bevat een naam object en een adres object., De naam op zijn beurt, bevat een Voornaam en een achternaam object; het adres object is samengesteld uit een straat object en een stad object. Als ik het heb over de persoon in dit artikel, dan heb ik het eigenlijk over dit hele netwerk van objecten.
Voorbeeld 4
dus waarom zouden we dit persoon object willen kopiëren? Een objectkopie, meestal een kloon genoemd, wordt gemaakt als we een object willen wijzigen of verplaatsen, met behoud van het oorspronkelijke object. Er zijn veel verschillende manieren om een object te kopiëren die u kunt leren over in een ander artikel., In dit artikel gebruiken we specifiek een copy constructor om onze kopieën te maken.
ondiepe kopie
laten we eerst praten over de ondiepe kopie. Een ondiepe kopie van een object kopieert het ‘hoofd’ object, maar kopieert niet de innerlijke objecten. De ‘innerlijke objecten’ worden gedeeld tussen het oorspronkelijke object en de kopie ervan. In ons Persoonsobject zouden we bijvoorbeeld een tweede persoon maken, maar beide objecten zouden dezelfde naam en Adresobjecten delen.
laten we eens kijken naar een codering voorbeeld. In Voorbeeld 5 hebben we onze class Person, die een naam en Adresobject bevat., De copy constructor neemt het object originalPerson en kopieert de referentievariabelen.
Voorbeeld 5
Het Probleem met de ondiepe kopie is dat de twee objecten niet onafhankelijk zijn. Als u het Naamobject van één persoon wijzigt, wordt de wijziging weerspiegeld in het object van de andere persoon.
laten we dit toepassen op een voorbeeld. Stel dat we een Persoonsobject hebben met een referentievariabele moeder; dan maken we een kopie van moeder en creëren we een tweede Persoonsobject, zoon. Als later in de code, de zoon probeert te bewegen () door het wijzigen van zijn adres object, de moeder beweegt met hem!,
Person mother = new Person(new Name(…), new Address(…));Person son = new Person(mother);son.moveOut(new Street(…), new City(…));
Voorbeeld 6
Dit gebeurt omdat onze moeder-en zoon-objecten hetzelfde Adresobject delen, zoals u kunt zien in Voorbeeld 7. Wanneer we het adres in een object veranderen, verandert het in beide!
Voorbeeld 7
diepe kopie
In tegenstelling tot de ondiepe kopie is een diepe kopie een volledig onafhankelijke kopie van een object. Als we ons Persoonsobject zouden kopiëren, zouden we de hele objectstructuur kopiëren.,
Voorbeeld 8
een verandering in het Adresobject van een persoon zou niet worden weerspiegeld in het andere object zoals u kunt zien in het diagram in Voorbeeld 8. Als we naar de code in Voorbeeld 9 kijken, kun je zien dat we niet alleen een copy constructor gebruiken op ons Persoonsobject, maar we gebruiken ook copy constructors op de innerlijke objecten.
Voorbeeld 9
Met deze diepe kopie kunnen we het moeder-zoon voorbeeld opnieuw proberen uit Voorbeeld 6. Nu is de zoon in staat om met succes te verhuizen!,
echter, dat is niet het einde van het verhaal. Om een echte diepe kopie te maken, moeten we alle geneste elementen van het Persoonsobject blijven kopiëren, totdat er alleen nog primitieve types en “onveranderlijke” over zijn. Laten we eens kijken naar de Street klasse om dit beter te illustreren:
voorbeeld 10
Het Street object bestaat uit twee instance variabelen – String naam en int nummer. int-getal is een primitieve waarde en geen object. Het is gewoon een eenvoudige waarde die niet gedeeld kan worden, dus door een tweede instantie variabele te maken, maken we automatisch een onafhankelijke kopie., String is onveranderlijk. Kortom, een onveranderlijk is een Object dat, eenmaal gecreëerd, nooit meer kan worden veranderd. Daarom kunt u het delen zonder een diepe kopie ervan te maken.
conclusie
tot slot wil ik het hebben over enkele coderingstechnieken die we in ons moeder-zoon voorbeeld hebben gebruikt. Alleen omdat een diepe kopie je de interne details van een object laat veranderen, zoals het Adresobject, betekent dit niet dat je dat moet doen., Dit zou de kwaliteit van de code verminderen, omdat het de Persoonsklasse kwetsbaarder zou maken voor veranderingen-wanneer de adresklasse wordt gewijzigd, moet u (mogelijk) ook wijzigingen toepassen op de Persoonsklasse. Bijvoorbeeld, als de Address class niet langer een Street object bevat, moeten we de MoveOut() methode in de Person class wijzigen bovenop de wijzigingen die we al hebben aangebracht in de Address class.
in Voorbeeld 6 van dit artikel koos ik er alleen voor om een nieuw Street en City object te gebruiken om het verschil tussen een ondiepe en een diepe kopie beter te illustreren., In plaats daarvan adviseer ik u een nieuw Adresobject toe te wijzen, effectief converteren naar een hybride van een ondiepe en een diepe kopie, zoals u kunt zien in Voorbeeld 10:
Person mother = new Person(new Name(…), new Address(…));Person son = new Person(mother);son.moveOut(new Address(...));
voorbeeld 11
in objectgeoriënteerde termen schendt dit de inkapseling en moet daarom worden vermeden. Encapsulation is een van de belangrijkste aspecten van objectgeoriënteerd programmeren. In dit geval had ik de inkapseling geschonden door toegang te krijgen tot de interne details van het Adresobject in onze Persoonsklasse., Dit schaadt onze code omdat we nu de Persoonsklasse in de adresklasse verstrikt hebben en als we wijzigingen aanbrengen in de adresklasse langs de lijn, kan het de Persoonsklasse schaden zoals ik hierboven heb uitgelegd. Terwijl je natuurlijk nodig hebt om uw verschillende klassen met elkaar te verbinden om een codering project hebben, wanneer u twee klassen te verbinden, je nodig hebt om de kosten en voordelen te analyseren.