cómo hacer una copia profunda de un objeto en Java

Introducción

Cuando queremos copiar un objeto en Java, hay dos posibilidades que debemos considerar: una copia superficial y una copia profunda.

la copia superficial es el enfoque cuando solo copiamos valores de campo y, por lo tanto, la copia puede depender del objeto original. En el enfoque de copia profunda, nos aseguramos de que todos los objetos del árbol se copien profundamente, de modo que la copia no dependa de ningún objeto existente anterior que pueda cambiar.,

en este artículo, compararemos estos dos enfoques y aprenderemos cuatro métodos para implementar la copia profunda.

más información:

Java Copy Constructor

Aquí está cómo crear constructores de copia en Java y por qué implementar Cloneable no es una gran idea.
Leer más →

Copiar Conjuntos en Java

Aprender diferentes maneras de cómo copiar un juego en Java.,
Read more →

copiando un HashMap en Java

aprenda varias técnicas para hacer copias superficiales y profundas del HashMap de Java
Read more →

Maven Setup

usaremos tres dependencias Maven: Gson, Jackson y Apache commons lang — para probar diferentes formas de realizar una copia profunda.

vamos a añadir estas dependencias a nuestro pom.xml:

las últimas versiones de Gson, Jackson y Apache Commons Lang se pueden encontrar en Maven Central.,

Model

para comparar diferentes métodos para copiar objetos Java, necesitaremos dos clases en las que trabajar:

class Address { private String street; private String city; private String country; // standard constructors, getters and setters}
class User { private String firstName; private String lastName; private Address address; // standard constructors, getters and setters}

Shallow Copy

una copia shallow es una copia en la que solo podemos copiar valores de campos de un objeto a otro:

en este caso pm != shallowCopy, lo que significa que son objetos diferentes, pero el problema es que cuando cambiamos cualquiera de las propiedades de la dirección original, esto también afectará la dirección de la shallowCopy.,

Nosotros no se preocupe si la Dirección era inmutable, pero no lo es:

Copia Profunda

Una copia profunda es una alternativa que soluciona este problema. Su ventaja es que al menos cada objeto mutable en el gráfico de objetos se copia recursivamente.

dado que la copia no depende de ningún objeto mutable que se haya creado anteriormente, no se modificará por accidente como vimos con la copia superficial.

en las siguientes secciones, mostraremos varias implementaciones de copia profunda y demostraremos esta ventaja.

5.1., Copy Constructor

la primera implementación que implementaremos se basa en constructores de copia:

public Address(Address that) { this(that.getStreet(), that.getCity(), that.getCountry());}
public User(User that) { this(that.getFirstName(), that.getLastName(), new Address(that.getAddress()));}

en la implementación anterior de la copia profunda, no hemos creado nuevas cadenas en nuestro constructor de copia porque String es una clase inmutable.

como resultado, no se pueden modificar por accidente. Veamos si esto funciona:

5.2. Interfaz Cloneable

la segunda implementación se basa en el método de clonación heredado de Object. Está protegido, pero tenemos que anularlo como público.,

también agregaremos una interfaz de marcador, Cloneable, a las clases para indicar que las clases son realmente cloneables.

agreguemos el método clone() A la clase Address:

Y ahora implementemos clone() para la clase User:

tenga en cuenta que el super.la llamada clone () devuelve una copia superficial de un objeto, pero establecemos copias profundas de campos mutables manualmente, por lo que el resultado es correcto:

bibliotecas externas

los ejemplos anteriores parecen fáciles, pero a veces no se aplican como una solución cuando no podemos agregar un constructor adicional o anular el método clone.,

esto puede suceder cuando no poseemos el código, o cuando el gráfico de objetos es tan complicado que no terminaríamos nuestro proyecto a tiempo si nos centráramos en escribir Constructores adicionales o implementar el método clone en todas las clases del gráfico de objetos.

entonces, ¿Qué? En este caso, podemos utilizar una biblioteca externa. Para lograr una copia profunda, podemos serializar un objeto y luego deserializarlo a un nuevo objeto.

veamos algunos ejemplos.

6.1., Apache Commons Lang

Apache Commons Lang tiene SerializationUtils#clone, que realiza una copia profunda cuando todas las clases en el gráfico de objetos implementan la interfaz Serializable.

si el método encuentra una clase que no es serializable, fallará y lanzará una excepción SerializationException sin marcar.

debido a eso, necesitamos agregar la interfaz Serializable a nuestras clases:

6.2. Serialización JSON con Gson

la otra forma de serializar es usar la serialización JSON. Gson es una biblioteca que se utiliza para convertir objetos en JSON y viceversa.,

a diferencia de Apache Commons Lang, GSON no necesita la interfaz Serializable para realizar las conversiones.

echemos un vistazo rápido a un ejemplo:

6.3. Serialización JSON Con Jackson

Jackson es otra biblioteca que admite la serialización JSON. Esta implementación será muy similar a la que usa Gson, pero necesitamos agregar el constructor predeterminado a nuestras clases.

veamos un ejemplo:

conclusión

¿Qué implementación debemos usar al hacer una copia profunda?, La decisión final a menudo dependerá de las clases que vamos a copiar y si poseemos las clases en el gráfico de objetos.

como siempre, los ejemplos de código completos para este tutorial se pueden encontrar en GitHub.

empezar con el Muelle 5 y el Resorte de Arranque 2, a través del aprendizaje del curso Primavera:

>> COMPRUEBE EL CURSO

Author: admin

Deja una respuesta

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