Apa itu serialVersionUID dan mengapa saya harus menggunakannya?

3000

Eclipse mengeluarkan peringatan saat a serialVersionUIDhilang.

Kelas serialable Foo tidak menyatakan bidang serialVersionUID akhir statis jenis panjang

Apa itu serialVersionUIDdan mengapa itu penting? Tolong tunjukkan contoh di mana hilang serialVersionUIDakan menyebabkan masalah.

ashokgelal
sumber
1
Temukan praktik yang baik tentang serialversionUID; dzone.com/articles/what-is-serialversionuid
ceyun

Jawaban:

2290

Dokumen untuk java.io.Serializablepenjelasan mungkin sama baiknya dengan yang akan Anda dapatkan:

Runtime serialisasi mengasosiasikan dengan setiap kelas serializable nomor versi, yang disebut a serialVersionUID, yang digunakan selama deserialisasi untuk memverifikasi bahwa pengirim dan penerima objek serial telah memuat kelas untuk objek yang kompatibel dengan serialisasi. Jika penerima telah memuat kelas untuk objek yang memiliki berbeda serialVersionUIDdari kelas pengirim yang sesuai, maka deserialisasi akan menghasilkan InvalidClassException. Kelas serializable dapat mendeklarasikan sendiri serialVersionUIDsecara eksplisit dengan mendeklarasikan bidang bernamaserialVersionUID yang harus statis, final, dan bertipe long:

ANY-ACCESS-MODIFIER static final long serialVersionUID = 42L;

Jika kelas serializable tidak secara eksplisit mendeklarasikan a serialVersionUID, maka runtime serialisasi akan menghitung serialVersionUIDnilai default untuk kelas tersebut berdasarkan berbagai aspek kelas, seperti yang dijelaskan dalam Spesifikasi Seriisasi Objek Java (TM). Namun, sangat disarankan bahwa semua kelas serial yang secara eksplisit mendeklarasikan serialVersionUIDnilai, karena serialVersionUIDperhitungan default sangat sensitif terhadap detail kelas yang dapat bervariasi tergantung pada implementasi kompiler, dan dengan demikian dapat mengakibatkan hal yang tidak terduga InvalidClassExceptionsselama deserialisasi. Oleh karena itu, untuk menjamin serialVersionUIDnilai yang konsisten di seluruh implementasi kompiler java yang berbeda, kelas serial harus mendeklarasikan serialVersionUIDnilai eksplisit . Sangat disarankan juga secara eksplisitserialVersionUIDdeklarasi menggunakan pengubah pribadi jika memungkinkan, karena deklarasi seperti itu hanya berlaku untuk serialVersionUIDbidang kelas segera menyatakan tidak berguna sebagai anggota yang diwarisi.

Jon Skeet
sumber
326
Jadi, apa yang Anda katakan pada dasarnya adalah bahwa jika pengguna tidak memahami semua materi di atas, kata pengguna tidak perlu khawatir tentang serialisasi? Saya yakin Anda menjawab "bagaimana?" daripada menjelaskan "mengapa?". Saya, untuk satu, tidak mengerti mengapa saya harus repot dengan SerializableVersionUID.
Ziggy
366
Alasannya ada di paragraf kedua: jika Anda tidak secara eksplisit menentukan serialVersionUID, nilai dihasilkan secara otomatis - tetapi itu rapuh karena bergantung pada implementasi kompiler.
Jon Skeet
14
Dan mengapa Eclipse mengatakan saya perlu "serialVersionUID final panjang statis swasta = 1L;" kapan saya memperpanjang kelas Exception?
JohnMerlino
21
@ JohnMerlino: Ya saya tidak berharap untuk mengatakan Anda membutuhkannya - tetapi mungkin menyarankan satu untuk membantu Anda membuat serialisasi pengecualian dengan benar. Jika Anda tidak akan membuat serial mereka, Anda benar-benar tidak perlu konstanta.
Jon Skeet
16
@JohnMerlino, untuk menjawab pertanyaan mengapa bagian dari Anda: Pengecualian mengimplementasikan Serializable dan gerhana memperingatkan bahwa Anda belum menetapkan serialVersionUID, yang akan menjadi ide yang baik (jika Anda tidak ingin membuat cerita bersambung kelas) untuk menghindari masalah yang posting JonSkeet menguraikan.
zpon
475

Jika Anda membuat cerita bersambung hanya karena Anda harus membuat cerita berseri untuk implementasi (siapa yang peduli jika Anda membuat cerita bersambung untuk HTTPSession, misalnya ... jika disimpan atau tidak, Anda mungkin tidak peduli tentang de-serializingobjek formulir), maka Anda dapat abaikan ini.

Jika Anda benar-benar menggunakan serialisasi, itu hanya masalah jika Anda berencana untuk menyimpan dan mengambil objek menggunakan serialisasi secara langsung. Ini serialVersionUIDmewakili versi kelas Anda, dan Anda harus menambahkannya jika versi kelas Anda saat ini tidak kompatibel dengan versi sebelumnya.

Sebagian besar waktu, Anda mungkin tidak akan menggunakan serialisasi secara langsung. Jika ini masalahnya, hasilkan default SerialVersionUIDdengan mengeklik opsi perbaikan cepat dan jangan khawatir.

MetroidFan2002
sumber
78
Saya akan mengatakan bahwa jika Anda tidak menggunakan serialisasi untuk penyimpanan permanen, Anda harus menggunakan @SuppressWarnings daripada menambahkan nilai. Ini mengacaukan kelas kurang, dan itu menjaga kemampuan mekanisme serialVersionUID untuk melindungi Anda dari perubahan yang tidak kompatibel.
Tom Anderson
25
Saya tidak melihat bagaimana menambahkan satu baris (penjelasan @SuppressWarnings) sebagai lawan dari baris lain (id serializable) "mengacaukan kelas kurang". Dan jika Anda tidak menggunakan serialisasi untuk penyimpanan permanen, mengapa Anda tidak menggunakan "1" saja? Anda tidak akan peduli dengan ID autogenerated dalam hal itu.
MetroidFan2002
71
@ MetroidFan2002: Saya pikir titik @ TomAnderson serialVersionUIDmelindungi Anda dari perubahan yang tidak kompatibel adalah valid. Menggunakan @SuppressWarningsdokumen niat lebih baik jika Anda tidak ingin menggunakan kelas untuk penyimpanan permanen.
AbdullahC
11
"Anda harus menambahkannya jika versi kelas Anda saat ini tidak kompatibel dengan versi sebelumnya:" Anda harus terlebih dahulu menjelajahi dukungan versi objek yang luas dari Serialisasi, (a) untuk memastikan bahwa kelas tersebut sekarang benar-benar kompatibel dengan serialisasi, yang spesifikasinya cukup sulit untuk dicapai; (b) untuk mencoba skema seperti metode baca / tulis kustom (), metode readResolve / writeReplace (), deklarasi serializableFields, dll, untuk memastikan aliran tetap kompatibel. Mengubah yang sebenarnya serialVersionUIDadalah pilihan terakhir, nasihat keputusasaan.
Marquis of Lorne
4
@ EJP peningkatan serialVersionUID muncul ketika penulis awal kelas telah diperkenalkan secara eksplisit. Saya akan mengatakan, jvm menghasilkan id serial, harus baik-baik saja. ini adalah jawaban terbaik yang saya lihat pada serialisasi.
overexchange
307

Saya tidak bisa melewatkan kesempatan ini untuk menyambungkan buku Josh Bloch, Effective Java (2nd Edition). Bab 11 adalah sumber yang sangat diperlukan pada serialisasi Java.

Per Josh, UID yang dibuat secara otomatis dihasilkan berdasarkan nama kelas, antarmuka yang diimplementasikan, dan semua anggota publik dan yang dilindungi. Mengubah semua ini dengan cara apa pun akan mengubah serialVersionUID. Jadi Anda tidak perlu mengacaukannya hanya jika Anda yakin tidak ada lebih dari satu versi kelas yang akan diserialisasi (baik lintas proses atau diambil dari penyimpanan di lain waktu).

Jika Anda mengabaikan mereka untuk saat ini, dan menemukan kemudian bahwa Anda perlu mengubah kelas dalam beberapa cara, tetapi mempertahankan kompatibilitas w / versi lama kelas, Anda dapat menggunakan alat JDK serialver untuk menghasilkan serialVersionUIDpada tua kelas, dan secara eksplisit mengatur bahwa di kelas baru. (Bergantung pada perubahan Anda, Anda mungkin perlu mengimplementasikan serialisasi khusus dengan menambahkan writeObjectdan readObjectmetode - lihat Serializablejavadoc atau bab 11.)

Scott Bale
sumber
33
Jadi orang mungkin repot dengan SerializableVersionUID jika ada yang khawatir tentang kompatibilitas dengan versi lama kelas?
Ziggy
10
Yup, jika versi yang lebih baru mengubah setiap anggota publik menjadi terlindungi, SerializableVersionUID default akan berbeda dan akan meningkatkan InvalidClassExceptions.
Chander Shivdasani
3
Nama kelas, antarmuka yang diimplementasikan, semua metode publik dan yang dilindungi, SEMUA variabel instan.
Achow
31
Perlu dicatat bahwa Joshua Bloch menyarankan agar untuk setiap kelas Serialable, Anda perlu menentukan versi serialnya. Kutipan dari bab 11: Apa pun bentuk serialisasi yang Anda pilih, deklarasikan UID versi serial eksplisit di setiap kelas serial yang Anda tulis. Ini menghilangkan UID versi serial sebagai sumber potensial ketidakcocokan (Butir 74). Ada juga manfaat kinerja yang kecil. Jika tidak ada versi serial UID yang disediakan, perhitungan yang mahal diperlukan untuk menghasilkannya saat runtime.
Ashutosh Jindal
136

Anda bisa memberi tahu Eclipse untuk mengabaikan peringatan serialVersionUID ini:

Jendela> Preferensi> Java> Kompiler> Kesalahan / Peringatan> Masalah Pemrograman Potensial

Jika Anda tidak tahu, ada banyak peringatan lain yang dapat Anda aktifkan di bagian ini (atau bahkan ada yang dilaporkan sebagai kesalahan), banyak yang sangat berguna:

  • Masalah Pemrograman Potensial: Kemungkinan penugasan boolean yang tidak disengaja
  • Masalah Pemrograman Potensial: Akses pointer kosong
  • Kode yang tidak perlu: Variabel lokal tidak pernah dibaca
  • Kode yang tidak perlu: Redundant null check
  • Kode yang tidak perlu: Pemain yang tidak perlu atau 'instanceof'

dan masih banyak lagi.

matt b
sumber
21
terbalik tetapi hanya karena poster asli tampaknya tidak membuat serialisasi apa pun. Jika poster itu mengatakan "Saya membuat serial tentang hal ini dan ..." maka Anda akan mendapatkan suara turun sebagai gantinya: P
John Gardner
3
Benar - saya berasumsi si penanya tidak mau diperingatkan
matt b
14
@Gardner -> setuju! Tetapi si penanya juga ingin tahu mengapa ia tidak mau diperingatkan.
Ziggy
8
Si penanya jelas peduli mengapa harus ada UID. Jadi sekadar menyuruhnya mengabaikan peringatan itu harus diturunkan.
cinqS
111

serialVersionUIDmemfasilitasi versi data serial. Nilainya disimpan dengan data saat membuat serial. Saat menghapus serialisasi, versi yang sama diperiksa untuk melihat bagaimana data bersambung cocok dengan kode saat ini.

Jika Anda ingin versi data Anda, Anda biasanya mulai dengan serialVersionUID0, dan menabraknya dengan setiap perubahan struktural ke kelas Anda yang mengubah data serial (menambah atau menghapus bidang non-transien).

Mekanisme de-serialisasi bawaan ( in.defaultReadObject()) akan menolak untuk menghilangkan serial dari data versi lama. Tetapi jika Anda mau, Anda dapat mendefinisikan readObject Anda sendiri () fungsi yang dapat membaca kembali data lama. Kode khusus ini kemudian dapat memeriksa serialVersionUIDuntuk mengetahui versi data yang ada dan memutuskan bagaimana untuk menghilangkan urutannya. Teknik versi ini berguna jika Anda menyimpan data bersambung yang bertahan beberapa versi kode Anda.

Tetapi menyimpan data serial untuk rentang waktu yang lama tidak terlalu umum. Adalah jauh lebih umum untuk menggunakan mekanisme serialisasi untuk secara sementara menulis data misalnya cache atau mengirimkannya melalui jaringan ke program lain dengan versi yang sama dari bagian-bagian yang relevan dari basis kode.

Dalam hal ini Anda tidak tertarik mempertahankan kompatibilitas ke belakang. Anda hanya peduli untuk memastikan bahwa basis kode yang berkomunikasi memang memiliki versi yang sama dari kelas yang relevan. Untuk memfasilitasi pemeriksaan semacam itu, Anda harus mempertahankanserialVersionUID seperti sebelumnya dan jangan lupa untuk memperbaruinya saat membuat perubahan pada kelas Anda.

Jika Anda lupa memperbarui bidang, Anda mungkin berakhir dengan dua versi berbeda dari kelas dengan struktur yang berbeda tetapi dengan yang sama serialVersionUID. Jika ini terjadi, mekanisme default (in.defaultReadObject() ) tidak akan mendeteksi perbedaan, dan mencoba untuk menderialisasi data yang tidak kompatibel. Sekarang Anda mungkin berakhir dengan kesalahan runtime kriptik atau kegagalan diam (bidang nol). Jenis kesalahan ini mungkin sulit ditemukan.

Jadi untuk membantu usecase ini, platform Java menawarkan Anda pilihan untuk tidak mengatur serialVersionUID secara manual. Sebagai gantinya, hash dari struktur kelas akan dihasilkan pada waktu kompilasi dan digunakan sebagai id. Mekanisme ini akan memastikan bahwa Anda tidak pernah memiliki struktur kelas yang berbeda dengan id yang sama, sehingga Anda tidak akan mendapatkan kegagalan serialisasi runtime yang sulit dilacak yang disebutkan di atas.

Tetapi ada bagian belakang dari strategi id yang dibuat secara otomatis. Yaitu bahwa id yang dihasilkan untuk kelas yang sama mungkin berbeda di antara kompiler (seperti yang disebutkan oleh Jon Skeet di atas). Jadi, jika Anda mengkomunikasikan data serial antara kode yang dikompilasi dengan kompiler yang berbeda, disarankan untuk mempertahankan id secara manual.

Dan jika Anda kompatibel dengan data Anda seperti dalam kasus penggunaan pertama yang disebutkan, Anda juga mungkin ingin mempertahankan id sendiri. Ini untuk mendapatkan id yang dapat dibaca dan memiliki kontrol yang lebih besar tentang kapan dan bagaimana mereka berubah.

Alexander Torstling
sumber
4
Menambahkan atau menghapus bidang yang tidak sementara tidak membuat serialisasi kelas tidak kompatibel. Karena itu tidak ada alasan untuk 'menabraknya' pada perubahan tersebut.
Marquis of Lorne
4
@ EJP: Hah? Menambahkan data pasti mengubah data serialisasi di dunia saya.
Alexander Torstling
3
@AlexanderTorstling Baca apa yang saya tulis. Saya tidak mengatakan itu tidak 'mengubah data serialisasi'. Saya mengatakan 'tidak membuat serialisasi kelas tidak kompatibel'. Itu bukan hal yang sama. Anda perlu membaca bab Versi dari Spesifikasi Serialisasi Objek.
Marquis of Lorne
3
@ EJP: Saya menyadari bahwa menambahkan bidang non-transient tidak berarti Anda membuat serialisasi kelas tidak kompatibel, tetapi itu adalah perubahan struktural yang mengubah data serial dan Anda biasanya ingin menabrak versi ketika melakukannya kecuali Anda menangani kompatibilitas ke belakang, yang juga saya jelaskan nanti di posting. Apa sebenarnya poin Anda?
Alexander Torstling
4
Maksud saya tetap persis apa yang saya katakan. Menambah atau menghapus bidang yang tidak transien tidak membuat kelas Serialisasi tidak kompatibel. Karena itu Anda tidak perlu membentur serialVersionUID setiap kali melakukannya.
Marquis of Lorne
72

Apa itu serialVersionUID dan mengapa saya harus menggunakannya?

SerialVersionUIDadalah pengidentifikasi unik untuk setiap kelas, JVMmenggunakannya untuk membandingkan versi kelas memastikan bahwa kelas yang sama digunakan selama Serialisasi dilakukan selama Deserialisasi.

Menentukan satu memberikan lebih banyak kontrol, meskipun JVM menghasilkan satu jika Anda tidak menentukan. Nilai yang dihasilkan dapat berbeda antara kompiler yang berbeda. Selain itu, kadang-kadang Anda hanya ingin untuk beberapa alasan untuk melarang deserialisasi objek serial lama [ backward incompatibility], dan dalam hal ini Anda hanya perlu mengubah serialVersionUID.

The javadocs untukSerializable mengatakan :

perhitungan serialVersionUID default sangat sensitif terhadap detail kelas yang dapat bervariasi tergantung pada implementasi kompiler, dan dengan demikian dapat menghasilkan InvalidClassExceptions yang tidak terduga selama deserialisasi.

Oleh karena itu, Anda harus mendeklarasikan serialVersionUID karena memberi kami lebih banyak kontrol .

Artikel ini memiliki beberapa poin bagus tentang topik ini.

Thalaivar
sumber
3
@Vinothbabu tetapi serialVersionUID adalah statis sehingga variabel statis tidak dapat diserialisasi. lalu kenapa jvm akan memeriksa versi, tanpa mengetahui apa versi dari objek deserialisasi
Kranthi Sama
3
Satu hal yang tidak disebutkan dalam jawaban ini adalah bahwa Anda dapat menyebabkan konsekuensi yang tidak diinginkan dengan membabi buta termasuk serialVersionUIDtanpa tahu mengapa. Komentar Tom Anderson tentang jawaban MetroidFan2002 membahas hal ini: "Saya akan mengatakan bahwa jika Anda tidak menggunakan serialisasi untuk penyimpanan permanen, Anda harus menggunakan @SuppressWarnings daripada menambahkan nilai. Ini mengacaukan kelas lebih sedikit, dan mempertahankan kemampuan dari mekanisme serialVersionUID untuk melindungi Anda dari perubahan yang tidak kompatibel. "
Kirby
7
serialVersionUIDadalah tidak sebuah 'identifier unik untuk masing-masing kelas'. Nama kelas yang sepenuhnya memenuhi syarat adalah itu. Ini adalah indikator versi .
Marquis of Lorne
58

Pertanyaan orisinal menanyakan 'mengapa ini penting' dan 'contoh' di mana ini Serial Version IDakan berguna. Yah saya telah menemukan satu.

Katakanlah Anda membuat Carkelas, instantiate, dan tulis itu ke aliran objek. Objek mobil rata duduk di sistem file untuk beberapa waktu. Sementara itu, jika Carkelas diubah dengan menambahkan bidang baru. Kemudian, ketika Anda mencoba membaca (yaitu deserialize) Carobjek yang diratakan , Anda mendapatkan java.io.InvalidClassException- karena semua kelas serial secara otomatis diberi pengidentifikasi unik. Pengecualian ini dilemparkan ketika pengidentifikasi kelas tidak sama dengan pengidentifikasi objek yang diratakan. Jika Anda benar-benar memikirkannya, pengecualian dilemparkan karena penambahan bidang baru. Anda dapat menghindari pengecualian ini dengan mengontrol versi sendiri dengan mendeklarasikan serialVersionUID eksplisit. Ada juga manfaat kinerja kecil dalam menyatakan secara eksplisitserialVersionUID(karena tidak harus dihitung). Jadi, ini adalah praktik terbaik untuk menambahkan serialVersionUID Anda sendiri ke kelas Serializable Anda segera setelah Anda membuatnya seperti yang ditunjukkan di bawah ini:

public class Car {
    static final long serialVersionUID = 1L; //assign a long value
}
Rupesh
sumber
Dan seseorang harus menetapkan nomor panjang acak, bukan 1L, untuk setiap UID.
abbas
4
@abbas 'Seseorang harus' melakukan itu mengapa? Tolong jelaskan apa bedanya.
Marquis of Lorne
Seperti namanya, itu mewakili versi kelas yang digunakan untuk membuat serial objek. Jika Anda memberikan nomor yang sama setiap kali, Anda tidak akan dapat menemukan kelas yang tepat untuk menghapus serialisasi. Jadi, setiap kali Anda membuat perubahan di kelas, lebih baik untuk mengubah versi juga.
abbas
2
@ Abbas, niat ini tidak berbenturan dengan menggunakan bilangan alami yang bertambah dari 1dan seterusnya.
Vadzim
2
@ BillK, saya pikir cek serialisasi terikat ke sepasang classname dan serialVersionUID. Jadi skema penomoran yang berbeda dari kelas dan perpustakaan yang berbeda tidak dapat mengganggu dengan cara apa pun. Atau apakah Anda menyiratkan perpustakaan yang menghasilkan kode?
Vadzim
44

Pertama, saya perlu menjelaskan apa itu serialisasi.

Serialisasi memungkinkan untuk mengkonversi objek ke aliran, untuk mengirim objek itu melalui jaringan ATAU Simpan ke file ATAU simpan ke dalam DB untuk penggunaan huruf.

Ada beberapa aturan untuk serialisasi .

  • Suatu objek hanya dapat serial jika kelasnya atau superclassnya mengimplementasikan antarmuka Serializable

  • Objek serializable (itu sendiri mengimplementasikan antarmuka Serializable) bahkan jika superclassnya tidak. Namun, superclass pertama dalam hierarki kelas serializable, yang tidak mengimplementasikan antarmuka Serializable, HARUS memiliki konstruktor no-arg. Jika ini dilanggar, readObject () akan menghasilkan java.io.InvalidClassException di runtime

  • Semua tipe primitif bersifat serial.

  • Bidang transien (dengan pengubah sementara) BUKAN serial, (yaitu, tidak disimpan atau dikembalikan). Kelas yang mengimplementasikan Serializable harus menandai bidang transien dari kelas yang tidak mendukung serialisasi (misalnya, aliran file).

  • Bidang statis (dengan pengubah statis) tidak bersambung.

Ketika Objectdiserialisasi, Java Runtime mengaitkan nomor versi serial alias, the serialVersionID.

Di mana kita memerlukan serialVersionID: Selama deserialization untuk memverifikasi bahwa pengirim dan penerima kompatibel dengan serialisasi. Jika penerima memuat kelas dengan yang berbedaserialVersionIDmaka deserialization akan berakhir denganInvalidClassCastException.
Kelas serializable dapat mendeklarasikan sendiriserialVersionUIDsecara eksplisit dengan mendeklarasikan bidang bernamaserialVersionUIDyang harus statis, final, dan bertipe panjang.

Mari kita coba ini dengan sebuah contoh.

import java.io.Serializable;    
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private String empname;
private byte empage;

public String getEmpName() {
    return name;
}
public void setEmpName(String empname) {
    this.empname = empname;
}
public byte getEmpAge() {
    return empage;
}
public void setEmpAge(byte empage) {
    this.empage = empage;
}

public String whoIsThis() {
    StringBuffer employee = new StringBuffer();
    employee.append(getEmpName()).append(" is ).append(getEmpAge()).append("
years old  "));
    return employee.toString();
}
}

Buat Obyek Serialize

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
public class Writer {
public static void main(String[] args) throws IOException {
    Employee employee = new Employee();
    employee.setEmpName("Jagdish");
    employee.setEmpAge((byte) 30);

    FileOutputStream fout = new 
FileOutputStream("/users/Jagdish.vala/employee.obj");
    ObjectOutputStream oos = new ObjectOutputStream(fout);
    oos.writeObject(employee);
    oos.close();
    System.out.println("Process complete");
}
}

Deserialize objek

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
public class Reader {
public static void main(String[] args) throws ClassNotFoundException, 
IOException {
    Employee employee = new Employee();
    FileInputStream fin = new 
    FileInputStream("/users/Jagdish.vala/employee.obj");
    ObjectInputStream ois = new ObjectInputStream(fin);
    employee = (Employee) ois.readObject();
    ois.close();
    System.out.println(employee.whoIsThis());
 }
}    

CATATAN: Sekarang ubah serialVersionUID dari kelas Karyawan dan simpan:

private static final long serialVersionUID = 4L;

Dan jalankan kelas Reader. Tidak mengeksekusi kelas Writer dan Anda akan mendapatkan pengecualian.

Exception in thread "main" java.io.InvalidClassException: 
com.jagdish.vala.java.serialVersion.Employee; local class incompatible: 
stream classdesc serialVersionUID = 1, local class serialVersionUID = 4
at java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:616)
at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1623)
at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1518)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1774)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1351)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:371)
at com.krishantha.sample.java.serialVersion.Reader.main(Reader.java:14)
JegsVala
sumber
Perbaiki saya jika saya salah - kelas lokal adalah salah satu yang saat ini Anda miliki / gunakan di classpath dan yang aliran adalah yang digunakan oleh pihak lain (mis. Server yang mengembalikan jawaban kepada Anda dan telah membuat serialkan tanggapan). Anda dapat menghadapi situasi ini ketika Anda berkomunikasi dengan server yang telah memperbarui lib pihak ke-3, tetapi Anda (klien) tidak pernah melakukan ini.
Victor
37

Jika Anda tidak akan perlu untuk membuat serial objek Anda ke byte array dan mengirim / menyimpannya, maka Anda tidak perlu khawatir tentang hal itu. Jika ya, maka Anda harus mempertimbangkan serialVersionUID Anda karena deserializer objek akan mencocokkannya dengan versi objek classloader-nya. Baca lebih lanjut di Spesifikasi Bahasa Jawa.

Eishay
sumber
10
Jika Anda tidak akan membuat serial objek, mengapa mereka Serializable?
erickson
7
@erickson - kelas induk mungkin serializable, katakanlah, ArrayList, tetapi Anda ingin objek Anda sendiri (katakanlah, daftar array yang dimodifikasi) untuk menggunakannya sebagai basis tetapi tidak akan pernah membuat serialisasi Koleksi yang Anda buat.
MetroidFan2002
5
Tidak disebutkan di mana pun di Spesifikasi Bahasa Jawa. Ini disebutkan dalam Spesifikasi Versi Objek.
Marquis of Lorne
4
Berikut ini tautan ke Spesifikasi Versi 8 Obyek Java .
Basil Bourque
34

Jika Anda mendapatkan peringatan ini di kelas Anda tidak pernah berpikir tentang serialisasi, dan bahwa Anda tidak menyatakan diri Anda sendiri implements Serializable , itu sering kali karena Anda mewarisi dari superclass, yang mengimplementasikan Serializable. Seringkali kemudian akan lebih baik untuk mendelegasikan ke objek seperti itu daripada menggunakan warisan.

Jadi, bukannya

public class MyExample extends ArrayList<String> {

    public MyExample() {
        super();
    }
    ...
}

melakukan

public class MyExample {
    private List<String> myList;

    public MyExample() {
         this.myList = new ArrayList<String>();
    }
    ...
}

dan dalam metode yang relevan panggil myList.foo()alih-alih this.foo()(atau super.foo()). (Ini tidak cocok dalam semua kasus, tetapi masih cukup sering.)

Saya sering melihat orang memperluas JFrame atau semacamnya, ketika mereka benar-benar hanya perlu mendelegasikan ini. (Ini juga membantu untuk melengkapi otomatis dalam suatu IDE, karena JFrame memiliki ratusan metode, yang tidak Anda perlukan ketika Anda ingin memanggil yang khusus di kelas Anda.)

Satu kasus di mana peringatan (atau serialVersionUID) tidak dapat dihindari adalah ketika Anda memperluas dari AbstractAction, biasanya dalam kelas anonim, hanya menambahkan metode actionPerformed-method. Saya pikir seharusnya tidak ada peringatan dalam hal ini (karena Anda biasanya tidak dapat membuat serialisasi dan deserialize kelas anonim semacam itu di berbagai versi kelas Anda), tetapi saya tidak yakin bagaimana kompiler dapat mengenali ini.

Paŭlo Ebermann
sumber
4
Saya pikir Anda benar bahwa komposisi lebih dari warisan lebih masuk akal, terutama ketika Anda mendiskusikan kelas-kelas seperti ArrayList. Namun, banyak kerangka kerja yang mengharuskan orang untuk memperluas dari superclasses abstrak yang dapat diserialkan (seperti kelas ActionForm Struts 1.2, atau ExtensionFunctionDefinition Saxon) dalam hal ini solusi ini tidak mungkin. Saya pikir Anda benar, alangkah baiknya jika peringatan itu diabaikan dalam kasus-kasus tertentu (seperti jika Anda memperpanjang dari kelas serializable abstrak)
piepera
2
Tentunya jika Anda menambahkan kelas sebagai anggota, daripada mewarisi dari itu, Anda harus menulis metode pembungkus untuk setiap metode dari kelas anggota yang ingin Anda gunakan, yang akan membuatnya tidak layak dalam sejumlah besar situasi .. kecuali java memiliki fungsi yang mirip dengan perl __AUTOLOAD, yang saya tidak tahu.
M_M
4
@M_M: Ketika Anda akan mendelegasikan banyak metode ke objek yang Anda bungkus, tentu saja tidak akan tepat untuk menggunakan delegasi. Tapi saya kira kasus ini adalah tanda kesalahan desain - pengguna kelas Anda (misalnya "MainGui") seharusnya tidak perlu memanggil banyak metode objek yang dibungkus (misalnya JFrame).
Paŭlo Ebermann
1
Apa yang saya tidak suka tentang delegasi adalah perlunya memegang referensi kepada delegasi. Dan setiap referensi berarti lebih banyak memori. Koreksi saya jika saya salah. Jika saya memerlukan CustomizedArrayList dari 100 objek maka ini tidak masalah, tetapi jika saya membutuhkan ratusan CustomizdeArrayLists dari beberapa objek maka penggunaan memori meningkat secara signifikan.
WVrock
2
Throwable adalah serializable, dan hanya Throwable yang dapat dilempar, jadi tidak mungkin untuk menentukan pengecualian yang tidak dapat serial. Delegasi tidak mungkin.
Phil
22

Untuk memahami pentingnya serialVersionUID bidang, orang harus memahami cara kerja serialisasi / deserialisasi.

Ketika objek kelas Serializable di-serialisasi, Java Runtime mengaitkan nomor versi serial (disebut sebagai serialVersionUID) dengan objek serial ini. Pada saat Anda membatalkan objek serial ini, Java Runtime cocok dengan serialVersionUID objek serial dengan serialVersionUID kelas. Jika keduanya sama maka hanya dilanjutkan dengan proses deserialisasi lebih lanjut melempar InvalidClassException.

Jadi kami menyimpulkan bahwa untuk membuat proses Serialization / Deserialization berhasil serialVersionUID objek serial harus setara dengan serialVersionUID kelas. Dalam hal jika programmer menentukan nilai serialVersionUID secara eksplisit dalam program maka nilai yang sama akan dikaitkan dengan objek serial dan kelas, terlepas dari platform serialisasi dan deserialisasi (misalnya serialisasi mungkin dilakukan pada platform seperti windows dengan menggunakan matahari atau MS JVM dan Deserialization mungkin berada pada platform Linux yang berbeda menggunakan Zing JVM).

Tetapi dalam kasus jika serialVersionUID tidak ditentukan oleh programmer maka saat melakukan Serialization \ DeSerialization objek apa pun, Java runtime menggunakan algoritma sendiri untuk menghitungnya. Algoritma perhitungan serialVersionUID ini bervariasi dari satu JRE ke yang lain. Mungkin juga bahwa lingkungan tempat objek bersambung menggunakan satu JRE (mis: SUN JVM) dan lingkungan tempat deserialisasi yang terjadi menggunakan Linux Jvm (tenaga). Dalam kasus seperti itu serialVersionUID yang terkait dengan objek serial akan berbeda dari serialVersionUID kelas yang dihitung pada lingkungan deserialisasi. Pada gilirannya deserialisasi tidak akan berhasil. Jadi untuk menghindari situasi / masalah seperti itu programmer harus selalu menentukan serialVersionUID dari kelas Serializable.

Nitesh Soni
sumber
2
Algoritma tidak bervariasi, tetapi sedikit kurang spesifik.
Marquis of Lorne
... algoritme tidak bervariasi, tetapi sedikit di bawah yang ditentukan ... artinya setiap jvm dapat bervariasi ..... @ user207421
AnthonyJClink
18

Jangan ganggu, perhitungan standarnya sangat bagus dan cukup untuk 99,9999% dari semua kasus. Dan jika Anda mengalami masalah, Anda dapat - seperti yang telah disebutkan - memperkenalkan UID sebagai pengaturan kebutuhan (yang sangat tidak mungkin)

grand johnson
sumber
2
Sampah. Cukup memadai dalam kasus di mana kelas tidak berubah. Anda tidak memiliki bukti untuk mendukung '99, 9999% '.
Marquis of Lorne
18

Adapun contoh di mana serialVersionUID yang hilang dapat menyebabkan masalah:

Saya sedang mengerjakan aplikasi Java EE ini yang terdiri dari modul Web yang menggunakan EJBmodul. Modul web memanggil EJBmodul dari jarak jauh dan melewati POJOyang mengimplementasikan Serializablesebagai argumen.

Ini POJO'skelas dikemas dalam jar EJB dan di dalam itu jar sendiri di WEB-INF / lib dari modul web. Mereka sebenarnya kelas yang sama, tetapi ketika saya mengemas modul EJB saya membongkar botol POJO ini untuk mengemasnya bersama dengan modul EJB.

Panggilan ke EJBgagal dengan Pengecualian di bawah ini karena saya belum menyatakannya serialVersionUID:

Caused by: java.io.IOException: Mismatched serialization UIDs : Source
 (Rep.
 IDRMI:com.hordine.pedra.softbudget.domain.Budget:5CF7CE11E6810A36:04A3FEBED5DA4588)
 = 04A3FEBED5DA4588 whereas Target (Rep. ID RMI:com.hordine.pedra.softbudget.domain.Budget:7AF5ED7A7CFDFF31:6227F23FA74A9A52)
 = 6227F23FA74A9A52
Henrique Ordine
sumber
16

Saya biasanya menggunakan serialVersionUIDdalam satu konteks: Ketika saya tahu itu akan meninggalkan konteks Java VM.

Saya akan tahu ini ketika saya menggunakan ObjectInputStreamdan ObjectOutputStreamuntuk aplikasi saya atau jika saya tahu perpustakaan / kerangka kerja yang saya gunakan akan menggunakannya. SerialVersionID memastikan Java VM yang berbeda dari berbagai versi atau vendor akan saling beroperasi dengan benar atau jika disimpan dan diambil di luar VM misalnya HttpSessiondata sesi dapat tetap ada bahkan selama restart dan peningkatan server aplikasi.

Untuk semua kasus lain, saya menggunakan

@SuppressWarnings("serial")

karena sebagian besar waktu standarnya serialVersionUIDcukup. Ini termasuk Exception, HttpServlet.

Archimedes Trajano
sumber
Itu tidak termasuk HttpServlet dalam wadah di mana mereka dapat ditukar, atau Pengecualian dalam RMI misalnya.
Marquis of Lorne
14

Data lapangan mewakili beberapa informasi yang disimpan di kelas. Kelas mengimplementasikan Serializableantarmuka, sehingga gerhana secara otomatis ditawarkan untuk mendeklarasikan serialVersionUIDbidang. Mari kita mulai dengan nilai 1 yang ditetapkan di sana.

Jika Anda tidak ingin peringatan itu datang, gunakan ini:

@SuppressWarnings("serial")
Mukti
sumber
11

Akan lebih baik jika CheckStyle dapat memverifikasi bahwa serialVersionUID pada kelas yang mengimplementasikan Serializable memiliki nilai yang baik, yaitu cocok dengan yang dihasilkan oleh generator id versi serial. Jika Anda memiliki proyek dengan banyak DTO serializable, misalnya, ingat untuk menghapus serialVersionUID yang ada dan membuat ulang itu menyakitkan, dan saat ini satu-satunya cara (yang saya tahu) untuk memverifikasi ini adalah dengan membuat ulang untuk setiap kelas dan membandingkannya dengan yang tua. Ini sangat menyakitkan.


sumber
8
Jika Anda mengatur serialVersionUID selalu dengan nilai yang sama dengan yang dihasilkan generator, Anda tidak benar-benar membutuhkannya sama sekali. Bagaimanapun, raison d'être-nya tetap sama setelah perubahan, ketika kelas masih kompatibel.
Paŭlo Ebermann
4
Alasannya adalah agar kompiler yang berbeda muncul dengan nilai yang sama untuk kelas yang sama. Seperti dijelaskan dalam javadocs (juga dijawab di atas), versi yang dihasilkan rapuh dan dapat bervariasi bahkan ketika kelas deserializable dengan benar. Selama Anda menjalankan tes ini pada kompiler yang sama setiap kali, itu harus aman. Tuhan membantu Anda jika Anda meningkatkan jdk dan aturan baru keluar, meskipun kode Anda tidak berubah.
Andrew Backer
2
Tidak perlu mencocokkan apa yang serialverakan diproduksi. -1
Marquis of Lorne
Secara umum tidak diperlukan sama sekali. Kasus @ AndrewBacker akan membutuhkan dua kompiler berbeda pada file .java yang sama dengan kedua versi file .class yang saling berkomunikasi - sebagian besar waktu Anda hanya membuat kelas dan mendistribusikannya. Jika itu masalahnya, maka tidak memiliki SUID akan bekerja dengan baik.
Bill K
1
Orang-orang yang benar-benar menggunakan Serialisasi untuk tujuan penyimpanan / pengambilan umumnya akan menetapkan serialVersionUIDke 1. Jika versi kelas yang lebih baru tidak kompatibel, tetapi masih harus dapat menangani data lama, Anda menambah nomor versi dan menambahkan kode khusus ke berurusan dengan format yang lebih lama. Saya menangis setiap kali saya melihat serialVersionUIDlebih dari 1 digit, baik karena itu angka acak (tidak berguna) atau karena kelas tampaknya perlu berurusan dengan lebih dari 10 versi yang berbeda.
john16384
11

SerialVersionUID digunakan untuk kontrol versi objek. Anda dapat menentukan serialVersionUID di file kelas Anda juga. Konsekuensi dari tidak menentukan serialVersionUID adalah bahwa ketika Anda menambahkan atau memodifikasi bidang apa pun di kelas maka kelas yang sudah bersambung tidak akan dapat dipulihkan karena serialVersionUID yang dihasilkan untuk kelas baru dan untuk objek serial lama akan berbeda. Proses serialisasi Java bergantung pada serialVersionUID yang benar untuk memulihkan keadaan objek serial dan melempar java.io.InvalidClassException dalam kasus ketidakcocokan serialVersionUID

Baca lebih lanjut: http://javarevisited.blogspot.com/2011/04/top-10-java-serialization-interview.html#ixzz3VQxnpOPZ

Neethu
sumber
9

Mengapa menggunakan SerialVersionUIDdalam Serializablekelas di Jawa?

Selama serialization, Java runtime membuat nomor versi untuk suatu kelas, sehingga ia bisa menghilangkan serialisasi nanti. Nomor versi ini dikenal sebagai SerialVersionUIDdi Jawa.

SerialVersionUIDdigunakan untuk versi data serial. Anda hanya dapat membatalkan serialisasi kelas jika SerialVersionUIDcocok dengan instance serial. Ketika kita tidak mendeklarasikan SerialVersionUIDdi kelas kita, Java runtime menghasilkannya untuk kita tetapi itu tidak direkomendasikan. Disarankan untuk mendeklarasikan SerialVersionUIDsebagai private static final longvariabel untuk menghindari mekanisme default.

Ketika Anda mendeklarasikan sebuah kelas sebagai Serializabledengan mengimplementasikan antarmuka penanda java.io.Serializable, Java runtime tetap instance dari kelas itu ke disk dengan menggunakan mekanisme Serialisasi default, asalkan Anda belum menyesuaikan proses menggunakan Externalizableantarmuka.

lihat juga Mengapa menggunakan SerialVersionUID di dalam kelas Serializable di Jawa

roottraveller
sumber
8

Jika Anda ingin mengubah sejumlah besar kelas yang tidak memiliki serialVersionUID di tempat pertama sambil mempertahankan kompatibilitas dengan kelas-kelas lama, alat-alat seperti IntelliJ Idea, Eclipse gagal karena mereka menghasilkan angka acak dan tidak bekerja pada banyak file dalam sekali jalan. Saya membuat skrip bash berikut (maaf untuk pengguna Windows, pertimbangkan untuk membeli Mac atau konversikan ke Linux) untuk membuat amandemen masalah serialVersionUID dengan mudah:

base_dir=$(pwd)                                                                  
src_dir=$base_dir/src/main/java                                                  
ic_api_cp=$base_dir/target/classes                                               

while read f                                                                     
do                                                                               
    clazz=${f//\//.}                                                             
    clazz=${clazz/%.java/}                                                       
    seruidstr=$(serialver -classpath $ic_api_cp $clazz | cut -d ':' -f 2 | sed -e 's/^\s\+//')
    perl -ni.bak -e "print $_; printf qq{%s\n}, q{    private $seruidstr} if /public class/" $src_dir/$f
done

Anda menyimpan skrip ini, katakan add_serialVersionUID.sh kepada Anda ~ / bin. Kemudian Anda menjalankannya di direktori root proyek Maven atau Gradle Anda seperti:

add_serialVersionUID.sh < myJavaToAmend.lst

.Lst ini mencakup daftar file java untuk menambahkan serialVersionUID dalam format berikut:

com/abc/ic/api/model/domain/item/BizOrderTransDO.java
com/abc/ic/api/model/domain/item/CardPassFeature.java
com/abc/ic/api/model/domain/item/CategoryFeature.java
com/abc/ic/api/model/domain/item/GoodsFeature.java
com/abc/ic/api/model/domain/item/ItemFeature.java
com/abc/ic/api/model/domain/item/ItemPicUrls.java
com/abc/ic/api/model/domain/item/ItemSkuDO.java
com/abc/ic/api/model/domain/serve/ServeCategoryFeature.java
com/abc/ic/api/model/domain/serve/ServeFeature.java
com/abc/ic/api/model/param/depot/DepotItemDTO.java
com/abc/ic/api/model/param/depot/DepotItemQueryDTO.java
com/abc/ic/api/model/param/depot/InDepotDTO.java
com/abc/ic/api/model/param/depot/OutDepotDTO.java

Script ini menggunakan alat JVK serialVer di bawah kap. Jadi pastikan $ JAVA_HOME / bin Anda ada di PATH.

schnell18
sumber
2
Memberi saya ide: selalu membuat ulang versi serial uid dengan alat seperti ini, tidak pernah dengan tangan, sebelum membuat rilis - dengan cara itu, Anda menghindari lupa untuk membuat perubahan ke kelas yang versi serialnya harusnya diubah karena aktual perubahan tidak kompatibel. Melacak itu secara manual sangat sulit.
Ignazio
6

Pertanyaan ini didokumentasikan dengan sangat baik di Java Efektif oleh Joshua Bloch. Buku yang sangat bagus dan wajib dibaca. Saya akan menguraikan beberapa alasan di bawah ini:

Runtime serialisasi datang dengan nomor yang disebut versi Serial untuk setiap kelas serializable. Nomor ini disebut serialVersionUID. Sekarang ada beberapa Matematika di belakang angka ini dan keluar berdasarkan bidang / metode yang didefinisikan di kelas. Untuk kelas yang sama, versi yang sama dihasilkan setiap waktu. Nomor ini digunakan selama deserialization untuk memverifikasi bahwa pengirim dan penerima objek serial telah memuat kelas untuk objek yang kompatibel sehubungan dengan serialisasi. Jika penerima telah memuat kelas untuk objek yang memiliki serialVersionUID berbeda dari kelas pengirim yang sesuai, maka deserialisasi akan menghasilkan InvalidClassException.

Jika kelas serializable Anda juga dapat mendeklarasikan serialVersionUID Anda secara eksplisit dengan mendeklarasikan bidang bernama "serialVersionUID" yang harus statis, final, dan bertipe panjang. Kebanyakan IDE seperti Eclipse membantu Anda menghasilkan string panjang itu.

Kutu buku
sumber
6

Setiap kali objek diserialisasi objek dicap dengan nomor ID versi untuk kelas objek. ID ini disebut serialVersionUID dan dihitung berdasarkan informasi tentang struktur kelas. Misalkan Anda membuat kelas Karyawan dan memiliki versi id # 333 (ditugaskan oleh JVM), Sekarang ketika Anda akan membuat serial objek objek dari kelas itu (Misalkan objek Karyawan), JVM akan menetapkan UID untuknya sebagai # 333.

Pertimbangkan situasi - di masa depan Anda perlu mengedit atau mengubah kelas Anda dan dalam hal ini ketika Anda memodifikasinya, JVM akan menetapkan UID baru (Misalkan # 444). Sekarang ketika Anda mencoba untuk menghapus tanda objek objek karyawan, JVM akan membandingkan ID versi objek serial (objek Karyawan) (# 333) dengan yang ada di kelas yaitu # 444 (Karena sudah diubah). Sebagai perbandingan JVM akan menemukan kedua versi UID berbeda dan karenanya Deserialization akan gagal. Karenanya jika serialVersionID untuk setiap kelas didefinisikan oleh programmer itu sendiri. Itu akan sama bahkan jika kelas berevolusi di masa depan dan karenanya JVM akan selalu menemukan kelas yang kompatibel dengan objek berseri meskipun kelas diubah. Untuk Info lebih lanjut, Anda dapat merujuk bab 14 dari HEAD FIRST JAVA.

Ali yang dikirimkan
sumber
1
Setiap kali kelas suatu objek diserialisasi maka serialVersionUIDakan dikirimkan. Itu tidak dikirim dengan setiap objek.
Marquis of Lorne
3

Penjelasan Sederhana:

  1. Apakah Anda membuat serialisasi data?

    Serialisasi pada dasarnya menulis data kelas ke file / stream / etc. De-serialisasi adalah membaca data itu kembali ke kelas.

  2. 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).

  3. Apakah ini versi pertama?

    Jika demikian, atur serialVersionUID=1L.

  4. Apakah ini versi prod kedua, ketiga, dll.?

    Sekarang Anda perlu khawatir 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.

gagarwa
sumber
2

'serialVersionUID' adalah nomor 64 bit yang digunakan untuk mengidentifikasi kelas secara unik selama proses deserialisasi. Ketika Anda membuat serial objek, serialVersionUID dari kelas juga ditulis ke file. Setiap kali Anda melakukan deserialisasi objek ini, java run time mengekstrak nilai serialVersionUID ini dari data serial dan membandingkan nilai yang sama terkait dengan kelas. Jika keduanya tidak cocok, maka 'java.io.InvalidClassException' akan dibuang.

Jika kelas serializable tidak secara eksplisit mendeklarasikan serialVersionUID, maka runtime serialisasi akan menghitung nilai serialVersionUID untuk kelas tersebut berdasarkan berbagai aspek kelas seperti bidang, metode dll., Anda dapat merujuk tautan ini untuk aplikasi demo.

Hari Krishna
sumber
1

Untuk menyampaikan cerita panjang pendek, bidang ini digunakan untuk memeriksa apakah data serial dapat di-deserialisasi dengan benar. Serialisasi dan deserialisasi sering dilakukan oleh salinan program yang berbeda - misalnya server mengubah objek menjadi string dan klien mengubah string yang diterima menjadi objek. Bidang ini memberi tahu bahwa keduanya beroperasi dengan ide yang sama tentang apa objek ini. Bidang ini membantu ketika:

  • Anda memiliki banyak salinan program yang berbeda di berbagai tempat (seperti 1 server dan 100 klien). Jika Anda akan mengubah objek Anda, mengubah nomor versi Anda dan lupa untuk memperbarui satu klien ini, ia akan tahu bahwa ia tidak mampu deserialization

  • Anda telah menyimpan data Anda di beberapa file dan kemudian Anda mencoba membukanya dengan versi terbaru dari program Anda dengan objek yang dimodifikasi - Anda akan tahu bahwa file ini tidak kompatibel jika Anda membiarkan versi Anda benar

Kapan itu penting?

Paling jelas - jika Anda menambahkan beberapa bidang ke objek Anda, versi yang lebih lama tidak akan dapat menggunakannya karena mereka tidak memiliki bidang ini dalam struktur objek mereka.

Kurang jelas - Saat Anda menghapus objek, bidang yang tidak ada dalam string akan disimpan sebagai NULL. Jika Anda telah menghapus bidang dari objek Anda, versi yang lebih lama akan menjaga bidang ini sebagai allways-NULL yang dapat menyebabkan kesalahan perilaku jika versi yang lebih lama mengandalkan data di bidang ini (toh Anda telah membuatnya untuk sesuatu, bukan hanya untuk bersenang-senang :-))

Paling tidak jelas - Terkadang Anda mengubah ide yang Anda masukkan ke dalam beberapa bidang makna. Misalnya ketika Anda berusia 12 tahun yang Anda maksud "sepeda" di bawah "sepeda", tetapi ketika Anda berusia 18 tahun Anda berarti "sepeda motor" - jika teman Anda akan mengundang Anda untuk "bersepeda melintasi kota" dan Anda akan menjadi satu-satunya yang datang dengan sepeda, Anda akan memahami betapa pentingnya untuk menjaga makna yang sama lintas bidang :-)

Stanislav Orlov
sumber
1

Pertama untuk menjawab pertanyaan Anda, ketika kami tidak mendeklarasikan SerialVersionUID di kelas kami, Java runtime menghasilkannya untuk kami, tetapi proses itu peka terhadap banyak data meta kelas termasuk jumlah bidang, jenis bidang, pengubah akses bidang, antarmuka diimplementasikan oleh kelas dll. Oleh karena itu disarankan untuk mendeklarasikannya sendiri dan Eclipse memperingatkan Anda tentang hal yang sama.

Serialisasi: Kita sering bekerja dengan objek-objek penting yang statusnya (data dalam variabel-variabel objek) sangat penting sehingga kita tidak dapat mengambil risiko kehilangannya karena kegagalan daya / sistem (atau) kegagalan jaringan jika mengirim keadaan objek ke objek lain mesin. Solusi untuk masalah ini bernama "Persistence" yang berarti bertahan (memegang / menyimpan) data. Serialisasi adalah salah satu dari banyak cara lain untuk mencapai kegigihan (dengan menyimpan data ke disk / memori). Saat menyimpan keadaan objek, penting untuk membuat identitas objek, agar dapat membacanya kembali dengan benar (penghapusan serialisasi). Identifikasi unik ini adalah ID SerialVersionUID.

Shanks D Siwa
sumber
0

Apa itu SerialVersionUID? Jawab: - Katakanlah ada dua orang, satu dari HQ dan lainnya dari ODC, keduanya akan melakukan serialisasi dan deserialisasi masing-masing. Dalam hal ini untuk mengautentikasi bahwa penerima yang berada di ODC adalah orang yang diautentikasi, JVM membuat ID unik yang dikenal sebagai SerialVersionUID.

Berikut ini penjelasan yang bagus berdasarkan skenario,

Mengapa SerialVersionUID?

Serialisasi : Pada saat serialisasi, dengan setiap sisi pengirim objek JVM akan menyimpan Pengidentifikasi Unik. JVM bertanggung jawab untuk menghasilkan ID unik tersebut berdasarkan file .class yang sesuai yang ada dalam sistem pengirim.

Deserialization : Pada saat deserialization, pihak penerima JVM akan membandingkan ID unik yang terkait dengan Object dengan kelas ID unik yaitu JVM juga akan membuat ID unik berdasarkan file .class yang sesuai yang ada dalam sistem penerima. Jika kedua ID unik cocok maka deserialisasi hanya akan dilakukan. Kalau tidak, kita akan mendapatkan Pengecualian Runtime mengatakan InvalidClassException. Identifier unik ini tidak lain adalah SerialVersionUID

forkdbloke
sumber