ProgramaciónDesarrollador Java

Explique las diferencias entre shallow copy y deep copy en Java. ¿Cómo se implementan y cuándo puede ser necesario su uso?

Supere entrevistas con el asistente de IA Hintsage

Respuesta

Shallow copy (copia superficial) crea un nuevo objeto, pero copia las referencias a los objetos anidados, no los objetos en sí. Deep copy (copia profunda) crea un nuevo objeto y copia recursivamente todos los objetos anidados en el original, de modo que no hay referencias compartidas entre la copia y el original.

Cuándo usar:

  • Shallow copy es suficiente si la estructura del objeto no contiene objetos anidados mutables, o si no se requiere modificar los objetos anidados.
  • Deep copy es necesario si la mutabilidad de los objetos anidados es crítica y cualquier modificación de la copia no debe reflejarse en el original.

Ejemplo de implementación:

// Ejemplo de clase con objeto anidado class Address { String city; Address(String city) { this.city = city; } } class Person implements Cloneable { String name; Address address; Person(String name, Address address) { this.name = name; this.address = address; } // Shallow copy public Person clone() throws CloneNotSupportedException { return (Person) super.clone(); } // Deep copy public Person deepClone() { return new Person(this.name, new Address(this.address.city)); } }

Pregunta trampa

¿Se puede implementar deep copy usando el método clone()?

Respuesta: No, el método estándar Object.clone() solo implementa "shallow copy". Para obtener deep copy, se debe clonar manualmente todos los campos anidados o usar bibliotecas externas (por ejemplo, Apache Commons Lang).

Ejemplo:

@Override public Person clone() throws CloneNotSupportedException { Person cloned = (Person) super.clone(); cloned.address = new Address(this.address.city); // deep copy manualmente return cloned; }

Historia

En un gran proyecto de CRM, después de implementar la copia de objetos a través de super.clone(), el desarrollador esperaba una completa independencia de las copias, pero al cambiar la dirección del usuario clonado, también cambiaba la dirección del original. El error se descubrió después del lanzamiento y causó confusión en la base de clientes.


Historia

Durante la serialización/deserialización para copiar profundamente, se eligió el mecanismo estándar Serializable. Sin embargo, se olvidó declarar uno de los campos del objeto anidado como Serializable, lo que resultó en errores durante la ejecución (NotSerializableException) y pérdida de datos en la copia de seguridad.


Historia

En uno de los microservicios, se utilizó la biblioteca BeanUtils.copyProperties para copiar DTO, sin darse cuenta de que el mecanismo solo implementa shallow copy. Después de la refactorización, aparecieron muchos errores no evidentes, cuando los cambios en las colecciones anidadas afectaban los datos originales obtenidos de la base de datos.