In Java, shallow copy is the copying of an object where only references to nested objects are copied, not the actual objects themselves. Therefore, changes to the nested objects will be reflected in both the copy and the original. Deep copy implies creating new independent copies of all nested objects.
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(); } } // Usage Person p1 = new Person("Ivan", new Address("Moscow")); Person p2 = (Person) p1.clone(); p2.address.city = "Petersburg"; System.out.println(p1.address.city); // Prints "Petersburg" — shallow 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; } }
Deep copying creates a completely independent copy of the object.
Question: Can the clone() method be used for guaranteed deep copying of any complex object?
Answer: No, the standard clone() only performs shallow copying. For deep copying, it is necessary to override clone() in all nested classes and explicitly clone all reference fields. Also, many collections and standard classes do not support deep cloning.
Story
A collection of users and their addresses was cloned using the clone() method without deep copying. After changing the address of one user, the address of another changed too, because only the reference was copied. Data "leaked" between users.
Story
During serialization of a complex object with nested collections, clone() was used instead of deep copy. After recovery from serialization, the data became inconsistent and NPE occurred.
Story
In the REST API, DTO objects were cloned by default using BeanUtils.copyProperties(), which led to sharing the same collection between clients. As a result, the user could see and edit someone else's data.