Clon de Java: constructores de copia profunda y superficial

Un clon es una copia exacta del original. En java, significa esencialmente la capacidad de crear un objeto con un estado similar al objeto original. El método java clone() proporciona esta funcionalidad.

En este post, exploraremos la mayoría de los aspectos importantes de Java clone.

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

¿Qué es el clon de Java?

Así que la clonación consiste en crear la copia del objeto original. Su significado en el diccionario es : «hacer una copia idéntica de».

De forma predeterminada, la clonación de java es ‘copia campo por campo’, es decir, ya que la clase Objeto no tiene idea de la estructura de la clase en la que se invocará el método clone ().

Entonces, JVM cuando se llama para clonar, haga lo siguiente:

  1. Si la clase solo tiene miembros de tipo de datos primitivos, se creará una copia completamente nueva del objeto y se devolverá la referencia a la nueva copia del objeto.
  2. Si la clase contiene miembros de cualquier tipo de clase, solo se copian las referencias de objetos a esos miembros y, por lo tanto, las referencias de miembros tanto en el objeto original como en el objeto clonado se refieren al mismo objeto.

Aparte del comportamiento predeterminado anterior, siempre puede anular este comportamiento y especificar el suyo propio. Esto se hace utilizando el método de sobreescritura clone(). Veamos cómo se hace.

Interfaz clonable de Java y método clone ()

Cada lenguaje que admite la clonación de objetos tiene sus propias reglas, al igual que java. En java, si una clase necesita soporte para la clonación, tiene que hacer lo siguiente:

  1. Debe implementar la interfaz Cloneable.
  2. Debe anular el método clone() de la clase de objeto.

Más información: La interfaz clonable está rota en java

Los documentos de Java sobre el método clone() se dan a continuación (formateados y extraídos).

  1. La primera instrucción garantiza que el objeto clonado tendrá una asignación de direcciones de memoria separada.
  2. La segunda instrucción sugiere que los objetos originales y clonados deben tener el mismo tipo de clase, pero no es obligatorio.
  3. La tercera instrucción sugiere que los objetos originales y clonados deben ser iguales usando el método equals (), pero no es obligatorio.

Entendamos el clon de Java con un ejemplo. Nuestra primera clase es de Employee clase con 3 atributos: idname y department.

Department clase tiene dos atributos: id y name.

Entonces, si necesitamos clonar la clase Employee, entonces necesitamos hacer algo como esto.

Genial, clonamos con éxito el objeto Employee. Pero, recuerde que tenemos dos referencias al mismo objeto y ahora ambas cambiarán el estado del objeto en diferentes partes de la aplicación. ¿Quieres ver cómo? Veamos.

Oops, los cambios de objetos clonados también son visibles en el original. De esta manera, los objetos clonados pueden causar estragos en el sistema si se les permite hacerlo. Cualquiera puede venir y clonar los objetos de la aplicación y hacer lo que quiera. ¿Podemos evitar esto??

la Respuesta es sí, podemos. Podemos evitar esto creando Java deep copy y utilizando constructores de copia. Aprenderemos sobre ellos más adelante en este post. Primero veamos qué es la clonación profunda y la clonación superficial en Java.

Copia superficial de Java

El clon superficial es «implementación predeterminada» en Java. En el método anulado clone, si no está clonando todos los tipos de objetos (no primitivos), entonces está haciendo una copia superficial.

Todos los ejemplos anteriores son de copia superficial sólo, porque no hemos clonado el Department objeto Employee clase clone método. Ahora, pasaré a la siguiente sección donde veremos la clonación profunda.

Copia profunda de Java

Clon profundo es el comportamiento deseado en la mayoría de los casos. En la copia profunda, creamos un clon que es independiente del objeto original y hacer cambios en el objeto clonado no debe afectar al objeto original.

Veamos cómo se crea la copia profunda en Java.

he modificado el Employee clases clone() método y añadió después de clone método Department clase.

Ahora probar nuestro código de clonación da el resultado deseado y el nombre del departamento no se modificará.

Aquí, cambiar el estado del objeto clonado no afecta al objeto original.

La clonación profunda requiere la satisfacción de seguir las reglas –

  • No es necesario copiar primitivas por separado.
  • Todas las clases de miembros en la clase original deben admitir la clonación y en el método de clonación de la clase original en contexto deben llamar a super.clone() en todas las clases de miembros.
  • Si alguna clase miembro no admite la clonación, en el método clonar, se debe crear una nueva instancia de esa clase miembro y copiar todos sus atributos uno por uno al nuevo objeto de clase miembro. Este nuevo objeto de clase miembro se establecerá en objeto clonado.

Más información: Clonación profunda mediante serialización en memoria

Constructores de copia Java

Los constructores de copia son constructores especiales en una clase que toma argumentos para su propio tipo de clase. Por lo tanto, cuando pase una instancia de clase a copy constructor, constructor devolverá una nueva instancia de clase con valores copiados de instancia de argumento. Le ayuda a clonar objetos con una interfaz clonable.

Veamos esto en el ejemplo:

public class PointOne {private Integer x;private Integer y;public PointOne(PointOne point){this.x = point.x;this.y = point.y;}}

Este método parece simple y es hasta que viene la herencia. Cuando define una clase extendiéndose por encima de la clase, también necesita definir un constructor similar allí. En la clase secundaria, necesita copiar atributos específicos secundarios y pasar el argumento al constructor de la superclase. Vamos a ver, ¿cómo?

Entonces, ¿estamos bien ahora? NO. El problema con la herencia es que el comportamiento exacto solo se identifica en tiempo de ejecución. Por lo tanto, en nuestro caso, si alguna clase pasa la instancia de PointTwo en el constructor de PointOne.

En este caso, usted va a obtener la instancia de PointOne en volver por donde has pasado instancia de PointTwo como argumento. Veamos esto en código:

Otra forma de crear un constructor de copia es tener métodos de fábrica estáticos. Toman el tipo de clase en el argumento y crean una nueva instancia usando otro constructor de la clase. Luego, estos métodos de fábrica copiarán todos los datos de estado a la nueva instancia de clase que se acaba de crear en el paso anterior y devolverán esta instancia actualizada.

Copia profunda de Java con serialización

La serialización es otra forma sencilla de clonar en profundidad. En este método, solo debe serializar el objeto a clonar y des-serializarlo. Obviamente, el objeto que necesita ser clonado debe implementar la interfaz Serializable.

Antes de seguir adelante, debo advertir que esta técnica no debe usarse a la ligera.

  1. En primer lugar, la serialización es enormemente cara. Podría ser fácilmente cien veces más caro que el método clone().
  2. En segundo lugar, no todos los objetos son Serializable.
  3. En tercer lugar, hacer una clase Serializable es complicado y no se puede confiar en todas las clases para hacerlo bien.

Leer más: Una guía para implementar la serialización en Java

Java clone – SerializationUtils

En Apache commons, SerializationUtils la clase también tiene función de utilidad para clonación profunda. Si se siente interesado, siga sus documentos oficiales.

<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.7</version></dependency>
SomeObject cloned = org.apache.commons.lang.SerializationUtils.clone(someObject);

Prácticas recomendadas de clonación de Java

  1. Cuando no sepa si puede llamar al método clone() de una clase en particular, ya que no está seguro de si está implementado en esa clase, puede verificar si la clase es una instancia de la interfaz «Cloneable» como se muestra a continuación.
    if(obj1 instanceof Cloneable){ obj2 = obj1.clone();}//Dont do this. Cloneable dont have any methodsobj2 = (Cloneable)obj1.clone();
  2. No se llama a ningún constructor en el objeto que se clona. Como resultado, es su responsabilidad, asegurarse de que todos los miembros se hayan configurado correctamente. Además, si realiza un seguimiento del número de objetos en el sistema contando la invocación de constructores, tiene un nuevo lugar adicional para incrementar el contador.

Espero que este post haya sido una actualización para ti y te ayude a obtener más información sobre el método clon de Java 8 y su uso correcto. También ayudará a responder preguntas de entrevistas de clones de Java.

Feliz Aprendizaje !!

Fue este artículo útil?

Háganos saber si le gustó la publicación. Es la única manera de mejorar.
No

Deja una respuesta

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