Ketika kelas mengimplementasikan Serializable di Eclipse, saya memiliki dua opsi: tambahkan default serialVersionUID(1L)
atau dibuat serialVersionUID(3567653491060394677L)
. Saya pikir yang pertama lebih keren, tetapi sering kali saya melihat orang menggunakan opsi kedua. Apakah ada alasan untuk menghasilkan long serialVersionUID
?
210
0L
hanya menggunakan awalnya.Jawaban:
Sejauh yang saya tahu, itu hanya untuk kompatibilitas dengan rilis sebelumnya. Ini hanya akan berguna jika Anda lalai menggunakan serialVersionUID sebelumnya, dan kemudian membuat perubahan yang Anda tahu harus kompatibel tetapi yang menyebabkan serialisasi rusak.
Lihat Spesifikasi Serialisasi Java untuk detail lebih lanjut.
sumber
Tujuan dari versi serialisasi UID adalah untuk melacak berbagai versi kelas untuk melakukan serialisasi objek yang valid.
Idenya adalah untuk menghasilkan ID yang unik untuk versi tertentu dari suatu kelas, yang kemudian diubah ketika ada detail baru yang ditambahkan ke kelas, seperti bidang baru, yang akan mempengaruhi struktur objek serial.
Selalu menggunakan ID yang sama, seperti
1L
berarti bahwa di masa depan, jika definisi kelas diubah yang menyebabkan perubahan pada struktur objek berseri, akan ada kemungkinan besar masalah muncul ketika mencoba melakukan deserialisasi objek.Jika ID dihilangkan, Java sebenarnya akan menghitung ID untuk Anda berdasarkan bidang objek, tapi saya percaya ini adalah proses yang mahal, jadi menyediakan satu secara manual akan meningkatkan kinerja.
Berikut adalah beberapa tautan ke artikel yang membahas tentang serialisasi dan versi berbagai kelas:
sumber
Note - It is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected serialVersionUID conflicts during deserialization, causing deserialization to fail.
. Komentar di atas diambil dari Java Object Serialization Specification versi 6.0Alasan utama untuk yang dihasilkan adalah untuk membuatnya kompatibel dengan versi kelas yang sudah ada yang sudah memiliki salinan.
sumber
Default "long" dari
serialVersionUID
adalah nilai default seperti yang didefinisikan oleh Spesifikasi Serialisasi Java , dihitung dari perilaku serialisasi default.Jadi, jika Anda menambahkan nomor versi default, kelas Anda (akan) membuat cerita bersambung lebih cepat asalkan tidak ada yang berubah secara struktural, tetapi Anda harus berhati-hati bahwa jika Anda mengubah kelas (menambah / menghapus bidang) Anda juga memperbarui nomor seri.
Jika Anda tidak harus kompatibel dengan bit stream yang ada, Anda bisa meletakkannya
1L
dan menambah versi sesuai kebutuhan ketika ada perubahan. Yaitu, ketika versi serialisasi standar dari kelas yang diubah akan berbeda dari versi standar dari kelas lama.sumber
Anda benar-benar harus membuat serialVersionUID setiap kali Anda mendefinisikan kelas yang mengimplementasikan
java.io.Serializable
. Jika tidak, satu akan dibuat untuk Anda secara otomatis, tetapi ini buruk. SerialVersionUID yang dibuat secara otomatis didasarkan pada tanda tangan metode kelas Anda, jadi jika Anda mengubah kelas Anda di masa depan untuk menambahkan metode (misalnya), deserializing versi "lama" kelas akan gagal. Inilah yang dapat terjadi:sumber
Jika Anda tidak menentukan serialVersionUID maka Java membuat satu dengan cepat. SerialVersionUID yang dihasilkan adalah angka itu. Jika Anda mengubah sesuatu di kelas Anda yang tidak benar-benar membuat kelas Anda tidak kompatibel dengan vernal bersambung sebelumnya tetapi mengubah hash, maka Anda perlu menggunakan serialVersionUID nomor sangat besar yang dihasilkan (atau nomor "diharapkan" dari pesan kesalahan) . Kalau tidak, jika Anda melacak semuanya sendiri, 0, 1, 2 ... lebih baik.
sumber
Ketika Anda menggunakan serialVersionUID (1L) daripada menghasilkan serialVersionUID (3567653491060394677L) Anda mengatakan sesuatu.
Anda mengatakan bahwa Anda 100% yakin bahwa tidak ada sistem yang akan menyentuh kelas ini yang memiliki versi serial yang tidak kompatibel dari kelas ini dengan nomor versi 1.
Jika Anda dapat memikirkan alasan apa pun untuk riwayat versi serialnya menjadi tidak dikenal, itu mungkin sulit dikatakan dengan percaya diri. Dalam masa hidupnya, kelas yang sukses akan dipertahankan oleh banyak orang, tinggal di banyak proyek, dan tinggal di banyak sistem.
Anda bisa menderita karenanya. Atau Anda bisa bermain lotre dengan harapan kalah. Jika Anda menghasilkan versi, Anda memiliki peluang kecil untuk kesalahan. Jika Anda menganggap "Hei, saya yakin belum ada yang menggunakan 1" peluang Anda lebih besar dari kecil. Justru karena kita semua berpikir 0 dan 1 itu keren sehingga Anda memiliki peluang lebih tinggi untuk memukulnya.
-
Ketika Anda menghasilkan serialVersionUID (3567653491060394677L) daripada menggunakan serialVersionUID (1L) Anda mengatakan sesuatu.
Anda mengatakan bahwa orang mungkin telah membuat atau membuat nomor versi lain secara manual selama sejarah kelas ini dan Anda tidak peduli karena Longs membuat angka besar.
Bagaimanapun, kecuali jika Anda benar-benar tahu sejarah nomor versi yang digunakan ketika membuat serial kelas di seluruh alam semesta di mana ia memiliki atau akan pernah ada, Anda mengambil risiko. Jika Anda punya waktu untuk memastikan 100% yakin 1 adalah AOK, lakukan saja. Jika itu terlalu sulit, silakan dan hasilkan secara buta. Anda lebih mungkin memenangkan lotre daripada melakukan kesalahan. Jika ya, beri tahu saya dan saya akan membelikan Anda bir.
Dengan semua pembicaraan tentang bermain lotre ini saya mungkin telah memberi Anda kesan bahwa serialVersionUID dibuat secara acak. Bahkan selama rentang angka didistribusikan secara merata untuk setiap nilai yang mungkin dari Long yang akan baik-baik saja. Namun, sebenarnya dilakukan dengan cara ini:
http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100
Satu-satunya perbedaan yang Anda dapatkan dengan itu adalah Anda tidak perlu sumber acak. Anda menggunakan perubahan di kelas itu sendiri untuk mengubah hasilnya. Namun menurut prinsip pigeonhole masih ada kemungkinan bisa salah dan bertabrakan. Sangat tidak mungkin. Jadi, semoga sukses membuat saya minum bir.
Namun, bahkan jika kelas hanya akan hidup dalam satu sistem dan satu basis kode, berpikir bahwa penambahan angka dengan tangan memberi Anda kesempatan nol tabrakan hanya berarti Anda tidak mengerti manusia. :)
sumber
Nah, serialVersionUID adalah pengecualian terhadap aturan bahwa "bidang statis tidak mendapatkan serial". ObjectOutputStream menulis setiap kali nilai serialVersionUID ke aliran output. ObjectInputStream membacanya kembali dan jika nilai yang dibaca dari aliran tidak setuju dengan nilai serialVersionUID dalam versi kelas saat ini, maka ia melempar InvalidClassException. Selain itu, jika tidak ada serialVersionUID yang secara resmi dideklarasikan di kelas untuk diserialisasi, kompiler secara otomatis menambahkannya dengan nilai yang dihasilkan berdasarkan bidang yang dideklarasikan di kelas.
sumber
Karena dalam banyak kasus id default tidak unik. jadi kami membuat id untuk membuat konsep unik.
sumber
Untuk menambahkan jawaban @David Schmitts, sebagai aturan praktis saya selalu menggunakan 1L default dari konvensi. Saya hanya perlu kembali dan mengubahnya beberapa kali, tetapi saya tahu bahwa ketika saya melakukan perubahan dan memperbarui nomor standar dengan satu setiap kali.
Di perusahaan saya saat ini, mereka memerlukan nomor yang dibuat secara otomatis jadi saya menggunakannya untuk konvensi, tapi saya lebih suka yang default. Pendapat saya adalah, jika ini bukan konvensi tempat Anda bekerja, gunakan default, kecuali Anda berpikir Anda akan terus mengubah struktur kelas serial Anda karena suatu alasan.
sumber
Tujuan dari versi serialisasi UID adalah untuk melacak berbagai versi kelas untuk melakukan serialisasi objek yang valid.
Idenya adalah untuk menghasilkan ID yang unik untuk versi tertentu dari suatu kelas, yang kemudian diubah ketika ada detail baru yang ditambahkan ke kelas, seperti bidang baru, yang akan mempengaruhi struktur objek serial.
Penjelasan Sederhana:
Apakah Anda membuat serialisasi data?
Serialisasi pada dasarnya menulis data kelas ke file / stream / etc. De-serialisasi adalah membaca data itu kembali ke kelas.
Apakah Anda berniat untuk berproduksi?
Jika Anda hanya menguji sesuatu dengan data yang tidak penting / palsu, maka jangan khawatir tentang hal itu (kecuali jika Anda menguji serialisasi secara langsung).
Apakah ini versi pertama?
Jika demikian, setel serialVersionUID = 1L.
Apakah ini versi prod kedua, ketiga, dll.?
Sekarang Anda perlu khawatir tentang serialVersionUID, dan harus memeriksanya secara mendalam.
Pada dasarnya, jika Anda tidak memperbarui versi dengan benar ketika Anda memperbarui kelas yang perlu Anda tulis / baca, Anda akan mendapatkan kesalahan ketika Anda mencoba membaca data lama.
sumber