ProgrammingJava Developer

Explain the differences between shallow copy and deep copy in Java. How are they implemented, and when might the need for their use arise?

Pass interviews with Hintsage AI assistant

Answer

Shallow copy creates a new object but copies references to nested objects instead of the actual objects. Deep copy creates a new object and recursively copies all objects nested within the original, ensuring that there are no shared references between the copy and the original.

When to use:

  • Shallow copy is sufficient if the object's structure does not contain mutable nested objects, or if there is no need to modify the nested objects.
  • Deep copy is necessary if the mutability of nested objects is critical and any modifications to the copy should not reflect on the original.

Example implementation:

// Example class with a nested object 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)); } }

Trick Question

Can deep copy be implemented using the clone() method?

Answer: No, the standard Object.clone() method only implements "shallow copy". To obtain a deep copy, all nested fields must be cloned manually or third-party libraries (e.g., Apache Commons Lang) should be used.

Example:

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

Story

In a large CRM project, after implementing object copying via super.clone(), the developer expected complete independence of copies, but when changing the address of the copied user, the original address also changed. The bug was identified only after the release and caused confusion in the client database.


Story

During serialization/deserialization for deep copying, the standard Serializable mechanism was chosen. However, one of the fields of the nested object was forgotten to be declared as Serializable, leading to errors during runtime (NotSerializableException) and data loss during backups.


Story

In one of the microservices, the BeanUtils.copyProperties library was used for copying DTO, not realizing that the mechanism only implements shallow copy. After refactoring, numerous non-obvious bugs appeared when changes in nested collections affected the original data fetched from the database.