Java'da nesnelerin kopyalanması, mevcut bir örneğin durumu ile aynı duruma sahip yeni bir nesne oluşturma sürecidir. Tarihsel olarak kopyalama, Java'nın ilk gelişim dönemlerinde nesneleri manuel olarak yeniden oluşturmadan kopyalama ihtiyacı doğduğunda önemli hale gelmiştir. Java, nesnelerin kopyalanması için evrensel bir yöntem sunmaz, bunun yerine clone() sözleşmesini ve kopyalayıcı yapıcı desenini kullanır.
clone() yöntemi, nesnelerin klonlanması için standart bir mekanizma sağlamak amacıyla Cloneable arayüzüne entegre edilmiştir, ancak uygulanması birçok nüansa sahiptir ve genellikle hataların ortaya çıkmasına neden olur.
Ana sorun, "kutu içinde" gerçek bir derin kopyalamanın olmaması ve yüzeysel klonlama (shallow copy) sırasında öngörülemeyen davranışların ortaya çıkma olasılığıdır. Kopyalayıcı yapıcı, hem yüzeysel hem de derin kopyalamayı gerçekleştirmeye izin verir, ancak açık bir uygulama gerektirir.
Karmaşık nesnelerin güvenli ve doğru bir şekilde kopyalanması için, kopyalayıcı yapıcıyı veya fabrika yöntemini kullanmak daha tercih edilirken, clone() yalnızca nesne gerçekten bu sözleşmeye uyuyorsa dikkatli bir şekilde kullanılmalıdır.
Kod örneği:
// clone() ile yüzeysel klonlama public class Address implements Cloneable { String city; public Address(String city) { this.city = city; } @Override public Address clone() throws CloneNotSupportedException { return (Address) super.clone(); } } public class Person implements Cloneable { String name; Address address; public Person(String name, Address address) { this.name = name; this.address = address; } @Override public Person clone() throws CloneNotSupportedException { Person copy = (Person) super.clone(); copy.address = address.clone(); // address'in derin kopyası return copy; } } // Kopyalayıcı yapıcı public class Person { String name; Address address; public Person(Person other) { this.name = other.name; this.address = new Address(other.address.city); } }
Anahtar özellikler:
clone() arayüzünün Cloneable uygulanmasını ve clone yönteminin geçersiz kılınmasını gerektirir.Soru 1: Eğer sınıf Cloneable’ı uygulamıyorsa, clone() çağrıldığında ne olur?
clone(), nesne Cloneable arayüzünü uygulamıyorsa CloneNotSupportedException fırlatır.
Soru 2: clone() ile klonlama varsayılan olarak derin midir?
Hayır, varsayılan olarak yalnızca yüzeysel klonlama uygulanır, tüm referanslar olduğu gibi kopyalanır.
Soru 3: Derin klonlama için kopyalayıcı yapıcı olmadan ne yapabilirim?
Hayır, süreci kontrol etmek istiyorsanız, iç nesnelerin kopyalanmasını ya yapıcıda ya da clone() içinde elle yazmanız gerekir.
Geliştirici, List<Product> alanına sahip Order sınıfında standart clone() kullanmıştır. Sonuç olarak, kopyadaki ürünler listesi değiştiğinde, orijinaldeki ürünler de değişmiş ve bu bir hataya yol açmıştır.
Artılar:
Eksiler:
Şirket, tüm alan varlıkları için kopyalayıcı yapıcıyı gerçekleştirmiş ve karmaşık iç içe nesnelerin klonlama sürecini testlerle desteklemiştir.
Artılar:
Eksiler: