en klon är en exakt kopia av originalet. I java betyder det i huvudsak förmågan att skapa ett objekt med liknande tillstånd som det ursprungliga objektet. Javaclone()
– metoden ger denna funktion.
i det här inlägget kommer vi att utforska de flesta viktiga aspekterna av Java klon.
Table of Contents1. What is clone?2. Java Cloneable interface and clone() method3. Shallow Copy4. Deep Copy5. Java Copy Constructors6. Deep copy with serialization7. Cloning using Apache commons8. Java clone best practices
Vad är Java klon?
så kloning handlar om att skapa kopian av originalobjektet. Dess ordlista betydelse är : ”gör en identisk kopia av”.
som standard är java-kloning ’fält för fältkopia’, dvs. eftersom Objektklassen inte har en aning om strukturen i klassen på vilken klon () – metod som ska åberopas.
så, JVM när det kallas för kloning, gör följande saker:
- Om klassen bara har primitiva datatypsmedlemmar skapas en helt ny kopia av objektet och referensen till den nya objektkopian returneras.
- Om klassen innehåller medlemmar av någon klasstyp kopieras endast objektreferenserna till dessa medlemmar och följaktligen hänvisar medlemsreferenserna i både det ursprungliga objektet och det klonade objektet till samma objekt.
bortsett från ovanstående standardbeteende kan du alltid åsidosätta detta beteende och ange ditt eget. Detta görs med överordnadclone()
metod. Låt oss se hur det görs.
Java Cloneable interface and clone() method
varje språk som stöder kloning av objekt har sina egna regler och det gör även java. I java, om en klass behöver stödja kloning måste den göra följande saker:
- Du måste implementera
Cloneable
gränssnitt. - Du måste åsidosätta
clone()
metod från Objektklass.
Läs mer: Cloneable gränssnitt bryts i java
Java docs om clone()
metoden ges nedan (formaterad och extrahera).
- första uttalandet garanterar att klonat objekt kommer att ha separat minnesadresstilldelning.
- andra uttalande föreslår att original och klonade objekt ska ha samma klass typ, men det är inte obligatoriskt.
- tredje uttalande föreslår att original och klonade objekt ska ha vara lika med equals () – metoden, men det är inte obligatoriskt.
låt oss förstå Java klon med exempel. Vår första klass är Employee
klass med 3 attribut – id
name
och department
.
Department
klassen har två attribut – id
och name
.
Så, om vi behöver klona Medarbetarklassen, måste vi göra något så här.
bra, vi klonade framgångsriktEmployee
– objektet. Men kom ihåg att vi har två referenser till samma objekt och nu kommer båda att ändra objektets tillstånd i olika delar av applikationen. Vill du se hur? Låt oss se.
Oops, klonade objektändringar är synliga i original också. På så sätt kan klonade objekt göra kaos i systemet om de får göra det. Vem som helst kan komma och klona dina applikationsobjekt och göra vad han vill. Kan vi förhindra detta??
svaret är ja, det kan vi. Vi kan förhindra detta genom att skapa Java deep copy och använda copy constructors. Vi kommer att lära oss om dem senare i det här inlägget. Låt oss först se vad som är djup kloning och grund kloning i Java.
Java Shallow Copy
Shallow clone är ”standardimplementering” i Java. I overriddenclone
– metoden, om du inte klonar alla objekttyper (inte primitiva), gör du en grund kopia.
alla ovanstående exempel är endast grunda kopior, eftersom vi inte har klonatDepartment
– objektet påEmployee
klassensclone
– metoden. Nu ska jag gå vidare till nästa avsnitt där vi kommer att se den djupa kloningen.
Java Deep Copy
Deep clone är det önskade beteendet i de flesta fall. I den djupa kopian skapar vi en klon som är oberoende av originalobjektet och att göra ändringar i det klonade objektet bör inte påverka originalobjektet.
Låt se hur djup kopia skapas i Java.
jag modifierade Employee
klasser clone()
– metoden och lade till följande clone
– metoden i Department
– klassen.
nu testar vår kloningskod ger önskat resultat och namnet på avdelningen kommer inte att ändras.
här påverkar det klonade objektets ändrade tillstånd inte det ursprungliga objektet.
så djup kloning kräver tillfredsställelse av följande regler –
- inget behov av att separat kopiera primitiva.
- Alla medlemsklasser i originalklassen ska stödja kloning och i klonmetod för originalklass i sammanhang ska man ringa
super.clone()
på alla medlemsklasser. - Om någon medlemsklass inte stöder kloning måste man skapa en ny instans av den medlemsklassen och kopiera alla dess attribut en efter en till ett nytt medlemsklassobjekt. Detta nya medlemsklassobjekt kommer att ställas in i klonat objekt.
Läs mer: Djupkloning med serialisering i minnet
Java Copy Constructors
Copy constructors är speciella konstruktörer i en klass som tar argument för sin egen klass Typ. Så när du skickar en instans av klass för att kopiera konstruktör, kommer konstruktören att returnera en ny instans av klass med värden kopierade från argumentinstans. Det hjälper dig att klona objekt med Klonbart gränssnitt.
Låt oss se detta i exempel:
public class PointOne {private Integer x;private Integer y;public PointOne(PointOne point){this.x = point.x;this.y = point.y;}}
denna metod ser enkel ut och det är tills kommer arv. När du definierar en klass genom att sträcka sig över klassen måste du definiera en liknande konstruktör där också. I barnklass måste du kopiera barnspecifika attribut och skicka argumentet till superklassens konstruktör. Låt oss se hur?
så, är vi bra nu? Nej. Problemet med arv är att exakt beteende identifieras endast vid körning. Så, i vårt fall om någon klass passerade instansen av PointTwo
I konstruktör av PointOne
.
i det här fallet får du instansen av PointOne
I gengäld där du passerade instans av PointTwo
som argument. Låt oss se detta i kod:
ett annat sätt att skapa en kopieringskonstruktör är att ha statiska fabriksmetoder. De tar klass typ i argument och skapa en ny instans med hjälp av en annan konstruktör av klassen. Sedan kopierar dessa fabriksmetoder all tillståndsdata till ny klassinstans som just skapats i föregående steg och returnerar den här uppdaterade instansen.
Java djup kopia med serialisering
serialisering är ett annat enkelt sätt att djup kloning. I den här metoden serialiserar du bara objektet som ska klonas och de-serialiserar det. Uppenbarligen bör objektet som måste klonas implementeraSerializable
gränssnitt.
innan jag går längre bör jag vara försiktig med att denna teknik inte ska användas lätt.
- först och främst är serialisering enormt dyr. Det kan lätt vara hundra gånger dyrare än
clone()
– metoden. - för det andra är inte alla objekt
Serializable
. - tredje, att göra en klass
Serializable
är knepigt och inte alla klasser kan lita på för att få det rätt.
Läs mer: en guide för att implementera serialisering i Java
Java clone – SerializationUtils
i Apache commons, SerializationUtils
klass har också verktygsfunktion för djup kloning. Om du känner dig intresserad följer du deras officiella dokument.
<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.7</version></dependency>
SomeObject cloned = org.apache.commons.lang.SerializationUtils.clone(someObject);
Java klon bästa praxis
- när du inte vet om du kan ringa
clone()
metod för en viss klass eftersom du inte är säker på om den är implementerad i den klassen kan du kontrollera om du inte kan ringaclone()
klassen är instans av”Cloneable
” gränssnitt enligt nedan.if(obj1 instanceof Cloneable){ obj2 = obj1.clone();}//Dont do this. Cloneable dont have any methodsobj2 = (Cloneable)obj1.clone();
- ingen konstruktör anropas på objektet som klonas. Som ett resultat är det ditt ansvar att se till att alla medlemmar har ställts in ordentligt. Om du håller reda på antalet objekt i systemet genom att räkna påkallandet av konstruktörer fick du också en ny extra plats för att öka räknaren.
Jag hoppas att det här inlägget har varit en uppdatering för dig och hjälper dig att få mer information om Java 8 klonmetod och det är korrekt användning. Det kommer också att hjälpa till att svara på Java klon intervjufrågor.
lyckligt lärande !!