Welcome to Our Website

Shallow vs. Deep Copy in Java

i den här artikeln från min Gratis Java 8-kurs kommer jag att diskutera skillnaden mellan en djup och en grund kopia. Du kan ladda ner bilderna och artikeln som PDF här.

Vad är en kopia?

till att börja med vill jag markera vad en kopia i Java är. Låt oss först skilja mellan en referenskopia och en objektkopia. En referenskopia, som namnet antyder, skapar en kopia av en referensvariabel som pekar på ett objekt., Om vi har ett bilobjekt, med en mycar-variabel som pekar på den och vi gör en referenskopia, kommer vi nu att ha två myCar-variabler, men fortfarande ett objekt.

exempel 1

en objektkopia skapar en kopia av själva objektet. Så om vi återigen kopierade vårt bilobjekt skulle vi skapa en kopia av själva objektet, liksom en andra referensvariabel som refererar till det kopierade objektet.

exempel 2

vad är ett objekt?,

både en djup kopia och en grund kopia är typer av objektkopior, men vad är egentligen ett objekt? Ofta, när vi pratar om ett objekt, talar vi om det som en enda enhet som inte kan brytas ner längre, som en ödmjuk kaffeböna. Men det är överförenklat.

exempel 3

säg att vi har ett personobjekt. Vårt personobjekt består faktiskt av andra objekt, som du kan se i Exempel 4. Vår Person innehåller ett namnobjekt och ett Adressobjekt., Namnet innehåller i sin tur ett förnamn och ett efternamn objekt; Adressobjektet består av ett Gatuobjekt och ett stadsobjekt. Så när jag pratar om Person i den här artikeln talar jag faktiskt om hela det här nätverket av objekt.

exempel 4

så varför skulle vi vilja kopiera det här Personobjektet? En objektkopia, vanligtvis kallad en klon, skapas om vi vill ändra eller flytta ett objekt, samtidigt som det ursprungliga objektet bevaras. Det finns många olika sätt att kopiera ett objekt som du kan lära dig om i en annan artikel., I den här artikeln kommer vi specifikt att använda en kopieringskonstruktör för att skapa våra kopior.

Grunt kopia

låt oss först prata om den grunda kopian. En grund kopia av ett objekt kopierar ”Huvud” – objektet, men kopierar inte de inre objekten. De ”inre objekten” delas mellan det ursprungliga objektet och dess kopia. I vårt personobjekt skulle vi till exempel skapa en andra Person, men båda objekten skulle dela samma namn och Adressobjekt.

låt oss titta på ett kodningsexempel. I exempel 5 har vi vår klassperson, som innehåller ett namn och Adressobjekt., Kopieringskonstruktören tar originaletobjektet och kopierar dess referensvariabler.

exempel 5

problemet med den grunda kopian är att de två objekten inte är oberoende. Om du ändrar namnobjektet för en Person kommer ändringen att återspeglas i det andra Personobjektet.

låt oss tillämpa detta på ett exempel. Säg att vi har ett personobjekt med en referensvariabel mamma; då gör vi en kopia av mamma, skapar ett andra Personobjekt, son. Om senare i koden försöker sonen att flyttaut () genom att ändra sitt Adressobjekt flyttar mamman med honom!,

Person mother = new Person(new Name(…), new Address(…));Person son = new Person(mother);son.moveOut(new Street(…), new City(…));

exempel 6

detta beror på att våra mor-och son-objekt delar samma Adressobjekt, som du kan se i Exempel 7. När vi ändrar adressen i ett objekt ändras det i båda!

exempel 7

djup kopia

Till skillnad från den grunda kopian är en djup kopia en helt oberoende kopia av ett objekt. Om vi kopierade vårt personobjekt skulle vi kopiera hela objektstrukturen.,

exempel 8

en ändring i Adressobjektet för en Person skulle inte återspeglas i det andra objektet som du kan se i diagrammet i Exempel 8. Om vi tittar på koden i exempel 9 kan du se att vi inte bara använder en kopieringskonstruktör på vårt personobjekt, men vi använder också kopieringskonstruktörer på de inre objekten också.

exempel 9

med den här djupa kopian kan vi försöka igen modersonens exempel från Exempel 6. Nu kan sonen framgångsrikt flytta ut!,

det är dock inte slutet på historien. För att skapa en sann djup kopia måste vi fortsätta kopiera alla Personobjektets kapslade element tills det bara finns primitiva typer och” Immutables ” kvar. Låt oss titta på Street-klassen för att bättre illustrera detta:

exempel 10

Street – objektet består av två instansvariabler-Strängnamn och int-nummer. int-nummer är ett primitivt värde och inte ett objekt. Det är bara ett enkelt värde som inte kan delas, så genom att skapa en andra instansvariabel skapar vi automatiskt en oberoende kopia., Sträng är en oföränderlig. Kort sagt, ett oföränderligt är ett objekt, som, en gång skapat, aldrig kan ändras igen. Därför kan du dela den utan att behöva skapa en djup kopia av den.

slutsats

Sammanfattningsvis vill jag prata om några kodningstekniker som vi använde i vårt exempel på mor-son. Bara för att en djup kopia låter dig ändra de interna detaljerna för ett objekt, till exempel Adressobjektet, betyder det inte att du borde., Att göra det skulle minska kodkvaliteten, eftersom det skulle göra personklassen mer ömtålig för ändringar-när Adressklassen ändras måste du (potentiellt)tillämpa ändringar i Personklassen också. Om Adressklassen till exempel inte längre innehåller ett Gatuobjekt måste vi ändra moveOut () – metoden i personklassen utöver de ändringar vi redan gjort i Adressklassen.

I exempel 6 i den här artikeln valde jag bara att använda ett nytt gatu-och Stadsobjekt för att bättre illustrera skillnaden mellan en grund och en djup kopia., Istället skulle jag rekommendera att du istället tilldelar ett nytt Adressobjekt och effektivt konverterar till en hybrid av en grund och en djup kopia, som du kan se i exempel 10:

Person mother = new Person(new Name(…), new Address(…));Person son = new Person(mother);son.moveOut(new Address(...));

exempel 11

i objektorienterade termer bryter detta inkapsling och bör därför undvikas. Inkapsling är en av de viktigaste aspekterna av objektorienterad programmering. I det här fallet hade jag brutit inkapsling genom att komma åt de interna detaljerna i Adressobjektet i vår personklass., Detta skadar vår kod eftersom vi nu har intrasslat personklassen i Adressklassen och om vi gör ändringar i Adressklassen längs linjen kan det skada personklassen som jag förklarade ovan. Medan du uppenbarligen behöver koppla ihop dina olika klasser för att ha ETT kodningsprojekt, när du ansluter två klasser måste du analysera kostnaderna och fördelarna.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *