Método clon() en Java

La clonación de objetos se refiere a la creación de una copia exacta de un objeto. Crea una nueva instancia de la clase del objeto actual e inicializa todos sus campos con exactamente el contenido de los campos correspondientes de este objeto.

Uso del operador de asignación para crear una copia de la variable de referencia

En Java, no hay un operador para crear una copia de un objeto. A diferencia de C++, en Java, si usamos el operador de asignación, creará una copia de la variable de referencia y no del objeto. Esto se puede explicar tomando un ejemplo. El siguiente programa demuestra lo mismo.

Java

// 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);
    }
}
Producción

10 20
100 20
100 20

Creando una copia usando el método clon()

La clase cuya copia del objeto se va a realizar debe tener un método de clonación público en ella o en una de sus clases principales.  

  • Cada clase que implemente clone() debe llamar a super.clone() para obtener la referencia del objeto clonado.
  • La clase también debe implementar la interfaz java.lang.Cloneable cuyo clon de objeto queremos crear; de lo contrario, arrojará CloneNotSupportedException cuando se llame al método de clonación en el objeto de esa clase.
  • Sintaxis:
  protected Object clone() throws CloneNotSupportedException

Uso del método clone() -Copia superficial

Tenga en cuenta : en el ejemplo de código a continuación, el método clone() crea un objeto completamente nuevo con un valor hashCode diferente, lo que significa que está en una ubicación de memoria separada. Pero debido a que el objeto de prueba c está dentro de Test2, los tipos primitivos han logrado una copia profunda, pero este objeto de prueba c aún se comparte entre t1 y t2. Para superar eso, hacemos explícitamente una copia profunda para la variable de objeto c, que se analiza más adelante. 

Java

// 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);
    }
}
Producción

10 20 300 40
100 20 300 40

En el ejemplo anterior, t1.clone devuelve la copia superficial del objeto t1. Para obtener una copia profunda del objeto, se deben realizar ciertas modificaciones en el método de clonación después de obtener la copia.

Copia profunda vs copia superficial

  • La copia superficial es el método de copiar un objeto y se sigue de forma predeterminada en la clonación. En este método, los campos de un objeto antiguo X se copian en el nuevo objeto Y. Mientras se copia el campo de tipo de objeto, la referencia se copia en Y, es decir, el objeto Y apuntará a la misma ubicación señalada por X. Si el valor del campo es un tipo primitivo, copia el valor del tipo primitivo.
  • Por lo tanto, cualquier cambio realizado en los objetos a los que se hace referencia en el objeto X o Y se reflejará en otros objetos.

Las copias superficiales son baratas y fáciles de hacer. En el ejemplo anterior, creamos una copia superficial del objeto .

Uso del método clone() – Deep Copy 

  • Si queremos crear una copia profunda del objeto X y colocarlo en un nuevo objeto Y, se crea una nueva copia de los campos de objetos a los que se hace referencia y estas referencias se colocan en el objeto Y. Esto significa que cualquier cambio realizado en los campos de objetos a los que se hace referencia en el objeto X o Y se reflejarán solo en ese objeto y no en el otro. En el siguiente ejemplo, creamos una copia profunda del objeto.
  • Una copia profunda copia todos los campos y hace copias de la memoria asignada dinámicamente a la que apuntan los campos. Una copia profunda ocurre cuando un objeto se copia junto con los objetos a los que se refiere.

Java

// 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);
    }
}
Producción

10 20 30 40
100 20 300 40

En el ejemplo anterior, podemos ver que se ha asignado un nuevo objeto para la clase Prueba para copiar un objeto que se devolverá al método de clonación. Debido a esto, t3 obtendrá una copia profunda del objeto t1. Por lo tanto, cualquier cambio realizado en los campos de objeto ‘c’ por t3 no se reflejará en t1.

Ventajas del método de clonación:  

  • Si usamos el operador de asignación para asignar una referencia de objeto a otra variable de referencia, apuntará a la misma ubicación de dirección del objeto anterior y no se creará ninguna copia nueva del objeto. Debido a esto, cualquier cambio en la variable de referencia se reflejará en el objeto original.
  • Si usamos un constructor de copia, entonces tenemos que copiar todos los datos explícitamente, es decir, tenemos que reasignar todos los campos de la clase en el constructor explícitamente. Pero en el método de clonación, este trabajo de crear una nueva copia lo realiza el propio método. Entonces, para evitar un procesamiento adicional, usamos la clonación de objetos.

 

Este artículo es una contribución de Ankit Agarwal. Si le gusta GeeksforGeeks y le gustaría contribuir, también puede escribir un artículo y enviarlo por correo a review-team@geeksforgeeks.org. Vea su artículo que aparece en la página principal de GeeksforGeeks y ayude a otros Geeks.

Escriba comentarios si encuentra algo incorrecto o si desea compartir más información sobre el tema tratado anteriormente. 

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *