ProgramaciónDesarrollador Java

Explique la diferencia entre shallow copy y deep copy de objetos en Java. ¿Cómo se pueden implementar y en qué situaciones es importante entender esta diferencia?

Supere entrevistas con el asistente de IA Hintsage

Respuesta.

En Java, shallow copy (copia superficial) es la copia de un objeto donde solo se copian las referencias a los objetos anidados, no los propios objetos. Por lo tanto, los cambios en los objetos anidados se reflejarán tanto en la copia como en el original. Deep copy (copia profunda) implica crear nuevas copias independientes de todos los objetos anidados.

Ejemplo de shallow copy (a través de clone)

class Address implements Cloneable { String city; Address(String city) { this.city = city; } protected Object clone() throws CloneNotSupportedException { return super.clone(); } } class Person implements Cloneable { String name; Address address; Person(String name, Address address) { this.name = name; this.address = address; } protected Object clone() throws CloneNotSupportedException { return super.clone(); } } // Uso Person p1 = new Person("Ivan", new Address("Moscow")); Person p2 = (Person) p1.clone(); p2.address.city = "Petersburg"; System.out.println(p1.address.city); // Imprimirá "Petersburg" — copia superficial

Ejemplo de deep copy

class Address implements Cloneable { String city; Address(String city) { this.city = city; } protected Object clone() throws CloneNotSupportedException { return new Address(this.city); } } class Person implements Cloneable { String name; Address address; Person(String name, Address address) { this.name = name; this.address = address; } protected Object clone() throws CloneNotSupportedException { Person cloned = (Person) super.clone(); cloned.address = (Address) address.clone(); return cloned; } }

La copia profunda permite crear una copia totalmente independiente del objeto.

Pregunta capciosa.

Pregunta: ¿Se puede usar el método clone() para garantizar la copia profunda de un objeto complejo arbitrario?

Respuesta: No, el clone() estándar solo hace copia superficial (shallow copy). Para la copia profunda, es necesario sobrescribir clone() en todas las clases anidadas y clonar explícitamente todos los campos de referencia. Además, muchas colecciones y clases estándar no admiten la clonación profunda.

Ejemplos de errores reales debido al desconocimiento de los matices del tema.


Historia

Una colección de usuarios y sus direcciones fue clonada utilizando el método clone() sin copia profunda. Después de cambiar la dirección de un usuario, la dirección del otro también cambió, porque se copió la referencia. Los datos en la base "fugaron" entre los usuarios.


Historia

Al serializar un objeto complejo con colecciones anidadas, se usó clone(), en lugar de una copia profunda. Tras la restauración de la serialización, los datos resultaron inconsistentes y se produjeron NPE.


Historia

En la API REST, los objetos DTO fueron clonados por defecto a través de BeanUtils.copyProperties(), lo que llevó a compartir la misma colección entre los clientes. Como resultado, un usuario podía ver y editar datos ajenos.