La clonazione di oggetti si riferisce alla creazione di una copia esatta di un oggetto. Crea una nuova istanza della classe dell'oggetto corrente e inizializza tutti i suoi campi esattamente con il contenuto dei campi corrispondenti di questo oggetto.
Metodi per eseguire la clonazione di oggetti in Java
Esistono 3 metodi per creare la clonazione di oggetti in Java menzionati di seguito:
- Utilizzo dell'Operatore di assegnazione per creare una copia della variabile di riferimento
- Creazione di una copia utilizzando il metodo clone()
- Utilizzo del metodo clone() – Deep Copy
1. Utilizzo dell'operatore di assegnazione per creare a copia del variabile di riferimento
In Java non esiste alcun operatore per creare una copia di un oggetto. A differenza del C++, in Java, se utilizziamo l'operatore di assegnazione, creerà una copia della variabile di riferimento e non dell'oggetto. Ciò può essere spiegato facendo un esempio. Il seguente programma dimostra lo stesso.
Di seguito è riportata l'implementazione dell'argomento precedente:
Giava
// Java program to demonstrate that assignment operator> // only creates a new reference to same object> import> java.io.*;> > // A test class whose objects are cloned> class> Test {> >int> x, y;> >Test()> >{> >x =>10>;> >y =>20>;> >}> }> > // Driver Class> class> Main {> >public> static> void> main(String[] args)> >{> >Test ob1 =>new> Test();> > >System.out.println(ob1.x +>' '> + ob1.y);> > >// Creating a new reference variable ob2> >// pointing to same address as ob1> >Test ob2 = ob1;> > >// Any change made in ob2 will> >// be reflected in ob1> >ob2.x =>100>;> > >System.out.println(ob1.x +>' '> + ob1.y);> >System.out.println(ob2.x +>' '> + ob2.y);> >}> }> |
>
>Produzione
10 20 100 20 100 20>
2. Creazione di una copia utilizzando il metodo clone()
La classe di cui deve essere creata la copia dell'oggetto deve avere un metodo clone pubblico al suo interno o in una delle sue classi madri.
- Ogni classe che implementa clone() dovrebbe chiamare super.clone() per ottenere il riferimento all'oggetto clonato.
- La classe deve anche implementare l'interfaccia java.lang.Cloneable di cui vogliamo creare il clone dell'oggetto, altrimenti lancerà CloneNotSupportedException quando il metodo clone viene chiamato sull'oggetto di quella classe.
Sintassi:
protected Object clone() throws CloneNotSupportedException>
i) Utilizzo del metodo clone() -Shallow Copy
Nota – Nell'esempio di codice seguente il metodo clone() crea un oggetto completamente nuovo con un valore hashCode diverso, il che significa che si trova in una posizione di memoria separata. Ma poiché l'oggetto Test c si trova all'interno di Test2, i tipi primitivi hanno ottenuto una copia profonda ma questo oggetto Test c è ancora condiviso tra t1 e t2. Per superare questo problema, eseguiamo esplicitamente una copia profonda per la variabile oggetto c, che verrà discussa più avanti.
Giava
// A Java program to demonstrate> // shallow copy using clone()> import> java.util.ArrayList;> > // An object reference of this class is> // contained by Test2> class> Test {> >int> x, y;> }> > // Contains a reference of Test and> // implements clone with shallow copy.> class> Test2>implements> Cloneable {> >int> a;> >int> b;> >Test c =>new> Test();> >public> Object clone()>throws> CloneNotSupportedException> >{> >return> super>.clone();> >}> }> > // Driver class> public> class> Main {> >public> static> void> main(String args[])> >throws> CloneNotSupportedException> >{> >Test2 t1 =>new> Test2();> >t1.a =>10>;> >t1.b =>20>;> >t1.c.x =>30>;> >t1.c.y =>40>;> > >Test2 t2 = (Test2)t1.clone();> > >// Creating a copy of object t1> >// and passing it to t2> >t2.a =>100>;> > >// Change in primitive type of t2 will> >// not be reflected in t1 field> >t2.c.x =>300>;> > >// Change in object type field will be> >// reflected in both t2 and t1(shallow copy)> >System.out.println(t1.a +>' '> + t1.b +>' '> + t1.c.x> >+>' '> + t1.c.y);> >System.out.println(t2.a +>' '> + t2.b +>' '> + t2.c.x> >+>' '> + t2.c.y);> >}> }> |
Katrina Kaif
>
>Produzione
10 20 300 40 100 20 300 40>
Nell'esempio precedente, t1.clone restituisce la copia superficiale dell'oggetto t1. Per ottenere una copia completa dell'oggetto è necessario apportare alcune modifiche al metodo clone dopo aver ottenuto la copia.
ii) Utilizzo del metodo clone() – Deep Copy
- Se vogliamo creare una copia completa dell'oggetto X e posizionarla in un nuovo oggetto Y, viene creata una nuova copia di tutti i campi degli oggetti di riferimento e questi riferimenti vengono inseriti nell'oggetto Y. Ciò significa che qualsiasi modifica apportata ai campi degli oggetti di riferimento nell'oggetto X o Y si rifletteranno solo in quell'oggetto e non nell'altro. Nell'esempio seguente, creiamo una copia profonda dell'oggetto.
- Una copia profonda copia tutti i campi e crea copie della memoria allocata dinamicamente a cui puntano i campi. Una copia profonda si verifica quando un oggetto viene copiato insieme agli oggetti a cui si riferisce.
Giava
// A Java program to demonstrate> // deep copy using clone()> > // An object reference of this> // class is contained by Test2> class> Test {> >int> x, y;> }> > // Contains a reference of Test and> // implements clone with deep copy.> class> Test2>implements> Cloneable {> >int> a, b;> > >Test c =>new> Test();> > >public> Object clone()>throws> CloneNotSupportedException> >{> >// Assign the shallow copy to> >// new reference variable t> >Test2 t = (Test2)>super>.clone();> > >// Creating a deep copy for c> >t.c =>new> Test();> >t.c.x = c.x;> >t.c.y = c.y;> > >// Create a new object for the field c> >// and assign it to shallow copy obtained,> >// to make it a deep copy> >return> t;> >}> }> > public> class> Main {> >public> static> void> main(String args[])> >throws> CloneNotSupportedException> >{> >Test2 t1 =>new> Test2();> >t1.a =>10>;> >t1.b =>20>;> >t1.c.x =>30>;> >t1.c.y =>40>;> > >Test2 t3 = (Test2)t1.clone();> >t3.a =>100>;> > >// Change in primitive type of t2 will> >// not be reflected in t1 field> >t3.c.x =>300>;> > >// Change in object type field of t2 will> >// not be reflected in t1(deep copy)> >System.out.println(t1.a +>' '> + t1.b +>' '> + t1.c.x> >+>' '> + t1.c.y);> >System.out.println(t3.a +>' '> + t3.b +>' '> + t3.c.x> >+>' '> + t3.c.y);> >}> }> |
>
>Produzione
10 20 30 40 100 20 300 40>
Nell'esempio sopra, possiamo vedere che un nuovo oggetto per la classe Test è stato assegnato per copiare un oggetto che verrà restituito al metodo clone. Per questo motivo t3 otterrà una copia profonda dell'oggetto t1. Pertanto, qualsiasi modifica apportata nei campi dell'oggetto 'c' da t3 non si rifletterà in t1.
Copia approfondita e copia superficiale
Esistono alcune differenze tra l'utilizzo di clone() come copia profonda e quella come copia superficiale, come menzionato di seguito:
- Copia superficiale è il metodo per copiare un oggetto ed è seguito per impostazione predefinita nella clonazione. In questo metodo, i campi di un vecchio oggetto X vengono copiati nel nuovo oggetto Y. Durante la copia del campo del tipo di oggetto, il riferimento viene copiato in Y, ovvero l'oggetto Y punterà alla stessa posizione indicata da X. Se il valore del campo è un tipo primitivo copia il valore del tipo primitivo.
- Pertanto, qualsiasi modifica apportata agli oggetti di riferimento nell'oggetto X o Y si rifletterà in altri oggetti.
Le copie superficiali sono economiche e semplici da realizzare. Nell'esempio precedente, abbiamo creato una copia superficiale di IL oggetto.
Perché utilizzare il metodo clone() o Vantaggi del metodo clone
- Se utilizziamo l'operatore di assegnazione per assegnare un riferimento a un oggetto a un'altra variabile di riferimento, allora punterà alla stessa posizione dell'indirizzo del vecchio oggetto e non verrà creata alcuna nuova copia dell'oggetto. Per questo motivo qualsiasi modifica nella variabile di riferimento si rifletterà nell'oggetto originale.
- Se utilizziamo un costruttore di copia, dobbiamo copiare tutti i dati in modo esplicito, ovvero dobbiamo riassegnare esplicitamente tutti i campi della classe nel costruttore. Ma nel metodo clone, il lavoro di creazione di una nuova copia viene eseguito dal metodo stesso. Quindi, per evitare elaborazioni aggiuntive, utilizziamo la clonazione degli oggetti.