Shallow copy (płytkie kopiowanie) tworzy nowy obiekt, ale kopiuje referencje do obiektów zagnieżdżonych, a nie same obiekty. Deep copy (głębokie kopiowanie) tworzy nowy obiekt i rekurencyjnie kopiuje wszystkie obiekty zagnieżdżone w oryginalnym, w ten sposób między kopią a oryginałem nie ma wspólnych referencji.
Kiedy używać:
Przykład realizacji:
// Przykład klasy z zagnieżdżonym obiektem 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)); } }
Czy można zrealizować deep copy za pomocą metody clone()?
Odpowiedź:
Nie, standardowa metoda Object.clone() realizuje tylko "shallow copy". Aby uzyskać deep copy, trzeba albo ręcznie sklonować wszystkie zagnieżdżone pola, albo skorzystać z zewnętrznych bibliotek (na przykład Apache Commons Lang).
Przykład:
@Override public Person clone() throws CloneNotSupportedException { Person cloned = (Person) super.clone(); cloned.address = new Address(this.address.city); // deep copy ręcznie return cloned; }
Historia
W dużym projekcie CRM, po wdrożeniu kopiowania obiektów przez
super.clone(), programista oczekiwał całkowitej niezależności kopii, ale zmieniając adres skopiowanego użytkownika, zmieniał się również adres oryginału. Błąd ujawniono dopiero po wydaniu i spowodował zamieszanie w bazie klientów.
Historia
Podczas serializacji/deserializacji do głębokiego kopiowania wybrano standardowy mechanizm Serializable. Jednak zapomniano zadeklarować jedno z pól zagnieżdżonego obiektu jako Serializable, co doprowadziło do błędów podczas pracy (NotSerializableException) i utraty danych podczas tworzenia kopii zapasowej.
Historia
W jednym z mikrousług używano biblioteki kopiowania BeanUtils.copyProperties do kopiowania DTO, nie zdając sobie sprawy, że mechanizm realizuje tylko shallow copy. Po refaktoryzacji pojawiło się wiele nieoczywistych błędów, gdy zmiana zagnieżdżonych kolekcji wpływała na oryginalne dane pobrane z bazy.