Saya bertanya-tanya apakah ada cara yang disarankan untuk melakukan klon / copy contoh dalam java.
Saya memiliki 3 solusi dalam pikiran, tetapi saya dapat melewatkan beberapa, dan saya ingin memiliki pendapat Anda
sunting: sertakan Bohzo propositon dan saring pertanyaan: ini lebih tentang kloning yang dalam daripada kloning yang dangkal.
Lakukan sendiri:
kode properti klon dengan tangan setelah properti dan periksa apakah instance yang dapat diubah juga dikloning.
pro:
- kontrol apa yang akan dilakukan
-
kontra eksekusi cepat :
- membosankan untuk menulis dan memelihara
- rawan bug (kegagalan copy / paste, properti yang hilang, properti yang bisa ditransfer kembali)
Gunakan refleksi:
Dengan alat refleksi Anda sendiri atau dengan penolong eksternal (seperti orang biasa jakarta) mudah untuk menulis metode penyalinan generik yang akan melakukan pekerjaan dalam satu baris.
pro:
- mudah untuk menulis
- tidak ada pemeliharaan
kontra:
- kurang kontrol apa yang terjadi
- rawan bug dengan objek bisa berubah jika alat refleksi tidak mengkloning sub objek juga
- eksekusi lebih lambat
Gunakan kerangka kerja klon:
Gunakan kerangka kerja yang melakukannya untuk Anda, seperti:
commons-lang SerializationUtils
Java Deep Cloning Library
Dozer
Kryo
pro:
- sama seperti refleksi
- kontrol lebih besar atas apa yang akan dikloning.
kontra:
- setiap instance yang dapat diubah sepenuhnya dikloning, bahkan pada akhir hierarki
- bisa sangat lambat untuk dieksekusi
Gunakan instrumentasi bytecode untuk menulis klon saat runtime
javassit , BCEL atau cglib mungkin digunakan untuk menghasilkan cloner khusus secepat satu tangan ditulis. Seseorang tahu lib menggunakan salah satu alat ini untuk tujuan ini?
Apa yang saya lewatkan di sini?
Mana yang akan Anda rekomendasikan ?
Terima kasih.
Jawaban:
Untuk kloning mendalam (klon seluruh hierarki objek):
commons-lang SerializationUtils - menggunakan serialisasi - jika semua kelas berada dalam kendali Anda dan Anda dapat memaksakan implementasi
Serializable
.Java Deep Cloning Library - menggunakan refleksi - dalam kasus ketika kelas atau objek yang ingin Anda kloning berada di luar kendali Anda (perpustakaan pihak ke-3) dan Anda tidak dapat membuatnya mengimplementasikan
Serializable
, atau dalam kasus Anda tidak ingin mengimplementasikanSerializable
.Untuk kloning dangkal (klon hanya properti tingkat pertama):
commons-beanutils BeanUtils - dalam banyak kasus.
Spring BeanUtils - jika Anda sudah menggunakan pegas dan karenanya memiliki utilitas ini di classpath.
Saya sengaja menghilangkan opsi "do-it-yourself" - API di atas memberikan kontrol yang baik atas apa yang harus dan tidak dikloning (misalnya menggunakan
transient
, atauString[] ignoreProperties
), sehingga menciptakan kembali roda tidak disukai.sumber
Buku Joshua Bloch memiliki seluruh bab berjudul "Item 10: Override Clone Judiciously" di mana ia masuk ke mengapa meng-override kloning sebagian besar adalah ide yang buruk karena spec Java untuk itu menciptakan banyak masalah.
Dia memberikan beberapa alternatif:
Gunakan pola pabrik sebagai pengganti konstruktor:
Gunakan copy constructor:
Semua kelas koleksi di Jawa mendukung copy constructor (mis. ArrayList baru (l);)
sumber
Copyable
antarmuka yang berisigetCopy()
metode. Cukup gunakan pola prototipe secara manual.newInstance()
metode ini danYum
konstruktor akan melakukan salinan dalam atau salinan dangkal?Karena versi 2.07 Kryo mendukung kloning yang dangkal / dalam :
Kryo cepat, di halaman mereka Anda dapat menemukan daftar perusahaan yang menggunakannya dalam produksi.
sumber
Gunakan XStream toXML / fromXML dalam memori. Sangat cepat dan telah ada untuk waktu yang lama dan semakin kuat. Objek tidak perlu Serializable dan Anda tidak harus menggunakan refleksi (meskipun XStream melakukannya). XStream dapat membedakan variabel yang menunjuk ke objek yang sama dan tidak secara tidak sengaja membuat dua salinan penuh dari instance. Banyak detail seperti itu telah dipalu selama bertahun-tahun. Saya telah menggunakannya selama beberapa tahun dan itu adalah suatu keharusan. Ini tentang mudah digunakan yang dapat Anda bayangkan.
atau
Untuk mengkloning,
Lebih ringkas:
sumber
Untuk objek yang rumit dan ketika kinerjanya tidak signifikan, saya menggunakan gson untuk membuat serialisasi objek menjadi teks json, lalu menghapus teks untuk mendapatkan objek baru.
gson yang berdasarkan refleksi akan bekerja dalam banyak kasus, kecuali bahwa
transient
bidang tidak akan disalin dan objek dengan referensi melingkar dengan sebabStackOverflowError
.sumber
Tergantung.
Untuk kecepatan, gunakan DIY. Untuk antipeluru, gunakan refleksi.
BTW, serialisasi tidak sama dengan refl, karena beberapa objek dapat memberikan metode serialisasi yang ditimpa (readObject / writeObject) dan mereka bisa buggy
sumber
Saya akan merekomendasikan cara DIY yang, dikombinasikan dengan kode hash () dan equals () yang bagus harus mudah dibuktikan dalam tes unit.
sumber
Saya sarankan untuk mengganti Object.clone (), panggil super.clone () terlebih dahulu dan kemudian panggil ref = ref.clone () pada semua referensi yang ingin Anda salin dalam. Ini kurang lebih Lakukan pendekatan sendiri tetapi perlu sedikit pengkodean.
sumber
Untuk menerapkan kloning dalam Serializable pada setiap kelas yang ingin Anda klon seperti ini
Dan kemudian gunakan fungsi ini:
seperti ini:
Obj newObject = (Obj)deepClone(oldObject);
sumber