SerialVersionUID nedir ve neden kullanmalıyım?


3000

Eclipse serialVersionUID, eksik olduğunda uyarılar verir .

Serileştirilebilir sınıf Foo, long türünde bir statik son serialVersionUID alanı bildirmez

Nedir serialVersionUIDve neden önemlidir? Lütfen eksik olanın serialVersionUIDsoruna neden olacağı bir örnek gösterin .


1
SerialversionUID hakkında iyi bir uygulama bulun; dzone.com/articles/what-is-serialversionuid
ceyun

Yanıtlar:


2290

İçin dokümanlar java.io.Serializablemuhtemelen alacağınız kadar iyi bir açıklamadır:

Serileştirme çalışma zamanı serileştirilebilir her sınıfla serileştirme serialVersionUIDsırasında serileştirilmiş bir nesnenin göndericisinin ve alıcısının serileştirme ile uyumlu olan bu nesne için sınıflar yüklediğini doğrulamak için kullanılan a adında bir sürüm numarası ile ilişkilendirilir . Alıcı, serialVersionUIDkarşılık gelen gönderenin sınıfından farklı bir nesne için bir sınıf yüklediyse, serileştirme bir InvalidClassException. Serileştirilebilir bir sınıf, statik, son ve tür olması gereken serialVersionUIDbir alan bildirerek kendi açıklamasını bildirebilir :serialVersionUIDlong

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

Serileştirilebilir bir sınıf açıkça a bildirmezse serialVersionUID, serileştirme çalışma zamanı serialVersionUID, Java (TM) Nesne Dizileme Belirtimi'nde açıklandığı gibi, sınıfın çeşitli yönlerine dayalı olarak bu sınıf için varsayılan bir değer hesaplar . Bununla birlikte, tüm serileştirilebilir sınıfların açık bir şekilde değerleri beyan etmesi şiddetle tavsiye edilir serialVersionUID, çünkü varsayılan serialVersionUIDhesaplama derleyici uygulamalarına bağlı olarak değişebilen ve dolayısıyla InvalidClassExceptionsserileştirme sırasında beklenmedik sonuçlara yol açabilecek sınıf ayrıntılarına karşı oldukça duyarlıdır . Bu nedenle, serialVersionUIDfarklı java derleyici uygulamaları arasında tutarlı bir değeri garanti etmek için serileştirilebilir bir sınıfın açık bir serialVersionUIDdeğer bildirmesi gerekir . Ayrıca,serialVersionUIDbildirimler mümkün olduğunda özel değiştiriciyi kullanır, çünkü bu bildirimler yalnızca derhal bildirilen sınıf serialVersionUIDalanlarına uygulanır, devralınan üyeler olarak yararlı değildir.


326
Yani, esas olarak söylediğiniz şey, eğer bir kullanıcı yukarıdaki malzemenin tamamını anlamadıysa, söz konusu kullanıcı serileştirme konusunda endişe etmiyor mu? "Nasıl?" "neden?" Birincisi, neden SerializableVersionUID ile uğraştığımı anlamıyorum.
Ziggy

366
Nedeni ikinci paragrafta: açıkça serialVersionUID belirtmezseniz, otomatik olarak bir değer oluşturulur - ancak bu derleyici uygulamasına bağımlı olduğu için kırılgandır.
Jon Skeet

14
Ve Eclipse neden "özel statik son uzun serialVersionUID = 1L;" Exception sınıfını ne zaman genişletirim?
JohnMerlino

21
@JohnMerlino: Gelirken söylemek istemem gerek tek - ama olabilir düşündüren doğru istisnalar seri çok yardımcı olması için bir tane. Onları serileştirmeyecekseniz, sabite ihtiyacınız yoktur.
Jon Skeet

16
@JohnMerlino, neden sorunuzu cevaplamak için: İstisna Serializable ve eclipse uygular, JonSkeet'in gönderdiği sorunları önlemek için (sınıfı serileştirmek istemiyorsanız) iyi bir fikir olacak bir serialVersionUID ayarlamadığınız konusunda uyarır. ana hatlarını.
zpon

475

Yalnızca uygulamanın uğruna serileştirmeniz gerekiyorsa ( HTTPSessionörneğin, bir ... dizisi için serileştirmeyi umursarsa ... depolanmış veya depolanmamışsa, muhtemelen de-serializingbir form nesnesini umursamıyorsunuz ), o zaman yapabilirsiniz Bunu yoksay.

Gerçekten serileştirme kullanıyorsanız, yalnızca doğrudan serileştirmeyi kullanarak nesneleri depolamayı ve almayı planlıyorsanız önemlidir. serialVersionUIDSınıf sürümünü temsil eder ve sınıfın güncel sürümü geriye önceki sürümü ile uyumlu değilse bunu artmalıdır.

Çoğu zaman, muhtemelen doğrudan serileştirmeyi kullanmayacaksınız. Bu durumda, SerialVersionUIDhızlı düzeltme seçeneğini tıklatarak bir varsayılan oluşturun ve endişelenmeyin.


78
Kalıcı depolama için serileştirme kullanmıyorsanız, değer eklemek yerine @SuppressWarnings kullanmanız gerektiğini söyleyebilirim. Sınıfı daha az karmaşıklaştırır ve sizi uyumsuz değişikliklerden korumak için serialVersionUID mekanizmasının rahatlığını korur.
Tom Anderson

25
Nasıl bir satır (@SuppressWarnings ek açıklama) başka bir satır (serializable id) aksine "sınıf daha az clutters" ekleyerek görmüyorum. Kalıcı depolama için serileştirme kullanmıyorsanız, neden sadece "1" i kullanmıyorsunuz? Bu durumda, otomatik olarak oluşturulan kimliği umursamazsınız.
MetroidFan2002

71
@ MetroidFan2002: Sanırım @ TomAnderson'ın serialVersionUIDsizi uyumsuz değişikliklerden koruma noktası geçerli. @SuppressWarningsSınıfı kalıcı depolama için kullanmak istemiyorsanız belgeleri kullanmak daha iyi olur.
AbdullahC

11
"Sınıfınızın geçerli sürümü önceki sürümüyle geriye dönük olarak uyumlu değilse artırmalısınız:" Önce Serialization'un kapsamlı nesne sürüm oluşturma desteğini keşfetmelisiniz, (a) sınıfın artık serileştirme ile uyumsuz olduğundan emin olmak için, şartname uyarınca başarılması oldukça zordur; (b) akışın uyumlu kaldığından emin olmak için özel read / writeObject () yöntemleri, readResolve / writeReplace () yöntemleri, serializableFields bildirimleri vb. gibi bir düzeni denemek. Gerçek serialVersionUIDolanı değiştirmek son çare, umutsuzluk avukatı.
user207421

4
SerialVersionUID'nin @EJP artışı, sınıfın ilk yazarı açıkça tanıtıldığında resme gelir. Jvm oluşturulan seri kimliği, iyi olmalı diyebilirim. Bu serileştirmede gördüğüm en iyi cevap .
Aralık'ta aşırı değişim

307

Josh Bloch'un Effective Java (2. Baskı) kitabını takmak için bu fırsatı kaçırmam . Bölüm 11, Java serileştirmesi için vazgeçilmez bir kaynaktır.

Josh'a göre, otomatik olarak oluşturulan UID, bir sınıf adına, uygulanan arabirimlere ve tüm ortak ve korunan üyelere göre oluşturulur. Bunlardan herhangi birini herhangi bir şekilde değiştirmek serialVersionUID. Bu nedenle, yalnızca sınıfın birden fazla sürümünün serileştirilmeyeceğinden eminseniz (süreçler arasında veya daha sonra depolamadan alınır) onlarla uğraşmanıza gerek yoktur.

Şimdilik bunları yoksayarsanız ve daha sonra sınıfı bir şekilde değiştirmeniz, ancak sınıfın eski sürümüyle uyumluluğu sürdürmeniz gerektiğini fark ederseniz , eski sınıfta oluşturmak için JDK aracı serialver'ı kullanabilir ve bunu açıkça ayarlayabilirsiniz. yeni sınıfta. (Değişikliklerinize bağlı olarak, ekleyerek ve yöntemlerle özel serileştirme uygulamanız gerekebilir - bkz. Javadoc veya yukarıda belirtilen bölüm 11.)serialVersionUIDwriteObjectreadObjectSerializable


33
Biri bir sınıfın eski sürümleri ile uyumluluk konusunda endişe duyuyorsa, SerializableVersionUID ile uğraşabilirsiniz?
Ziggy

10
Evet, yeni sürüm herhangi bir genel üyeyi korumalı olarak değiştirirse, varsayılan SerializableVersionUID farklı olacaktır ve bir InvalidClassExceptions oluşturacaktır.
Chander Shivdasani

3
sınıf Adı, uygulanan arabirimler, tüm ortak ve korunan yöntemler, ALL örnek değişkenleri.
13'te

31
Joshua Bloch'un her Serializable sınıfı için seri sürüm kullanıcı kimliğini belirtmeye değer olduğunu belirtmekte fayda var . Bölüm 11'den alıntı: Hangi serileştirilmiş formu seçtiğinizden bağımsız olarak, yazdığınız her serileştirilebilir sınıfta açık bir seri sürüm UID'si bildirin. Bu, potansiyel bir uyumsuzluk kaynağı olarak seri sürüm UID'sini ortadan kaldırır (Madde 74). Ayrıca küçük bir performans avantajı vardır. Seri sürüm UID'si sağlanmamışsa, çalışma zamanında bir tane oluşturmak için pahalı bir hesaplama gerekir.
Ashutosh Jindal

136

Eclipse'e şu serialVersionUID uyarılarını yoksaymasını söyleyebilirsiniz:

Pencere> Tercihler> Java> Derleyici> Hatalar / Uyarılar> Potansiyel Programlama Sorunları

Bilmiyorsanız, bu bölümde etkinleştirebileceğiniz birçok uyarı var (hatta bazılarını hata olarak bildirdiyseniz), birçoğu çok yararlıdır:

  • Olası Programlama Sorunları: Olası yanlışlıkla boole ataması
  • Potansiyel Programlama Sorunları: Boş işaretçi erişimi
  • Gereksiz kod: Yerel değişken asla okunmaz
  • Gereksiz kod: Gereksiz boş kontrol
  • Gereksiz kod: Gereksiz döküm veya 'instanceof'

ve daha fazlası.


21
ancak orijinal afişin hiçbir şeyi seri hale getirmediği için oy verin. Eğer poster "bu şeyi seri hale getiriyorum ve ..." derse, o zaman onun yerine oy alırsınız: P
John Gardner

3
Doğru - soru soran sadece uyarılmak istemiyordu varsayıyordu
matt b

14
@Gardner -> kabul etti! Ancak soru soran kişi neden uyarılmak istemeyeceğini de bilmek istiyor.
Ziggy

8
Soru soran, neden bir kullanıcı kimliği olması gerektiğine açıktır. Bu yüzden sadece uyarıyı görmezden gelmesini söylemenin reddedilmesi gerekir.
cinqS

111

serialVersionUIDserileştirilmiş verilerin sürümlendirilmesini kolaylaştırır. Serileştirilirken değeri verilerle birlikte kaydedilir. Serileştirmeyi kaldırırken, serileştirilmiş verilerin geçerli kodla nasıl eşleştiğini görmek için aynı sürüm kontrol edilir.

Verilerinizi sürümlendirmek istiyorsanız, normalde serialVersionUID0 ile başlarsınız ve serileştirilmiş verileri değiştiren (geçici olmayan alanları ekleyerek veya kaldırarak) sınıfınızdaki her yapısal değişiklikle bu verileri vurursunuz.

Yerleşik serileştirme mekanizması ( in.defaultReadObject()), verilerin eski sürümlerinden serileştirmeyi reddedecektir. Ancak isterseniz eski verileri okuyabilen kendi readObject () işlevinizi tanımlayabilirsiniz . Bu özel kod daha sonra serialVersionUIDverinin hangi sürümde olduğunu bilmek ve verilerin seri dışı bırakılmasına karar vermek için kontrol edebilir. Bu sürüm oluşturma tekniği, kodunuzun çeşitli sürümlerinden sağ çıkmış olan serileştirilmiş verileri depolarsanız yararlıdır.

Ancak bu kadar uzun bir süre için serileştirilmiş verilerin depolanması çok yaygın değildir. Örneğin bir önbelleğe geçici olarak veri yazmak veya ağ üzerinden kod tabanının ilgili bölümlerinin aynı sürümüne sahip başka bir programa veri göndermek için serileştirme mekanizmasını kullanmak çok daha yaygındır.

Bu durumda geriye dönük uyumluluğu korumakla ilgilenmezsiniz. Yalnızca iletişim kuran kod tabanlarının ilgili sınıfların aynı sürümlerine sahip olduğundan emin olmakla ilgilenirsiniz. Böyle bir kontrolü kolaylaştırmak için, serialVersionUIDtıpkı daha önce olduğu gibi devam etmeli ve sınıflarınızda değişiklik yaparken güncellemeyi unutmamalısınız.

Alanı güncellemeyi unutursanız, bir sınıfın farklı yapıya sahip ancak aynı olan iki farklı sürümü olabilir serialVersionUID. Bu durumda, varsayılan mekanizma ( in.defaultReadObject()) herhangi bir fark algılamaz ve uyumsuz verilerin serileştirilmesini kaldırmaya çalışır. Artık şifreli bir çalışma zamanı hatası veya sessiz hata (boş alanlar) ile sonuçlanabilir. Bu tür hataları bulmak zor olabilir.

Dolayısıyla, bu kullanıcı tabanına yardımcı olmak için Java platformu, serialVersionUIDmanuel olarak ayarlamama seçeneği sunar . Bunun yerine, derleme zamanında sınıf yapısının bir karması oluşturulur ve id olarak kullanılır. Bu mekanizma, asla aynı kimliğe sahip farklı sınıf yapılarına sahip olmadığınızdan emin olur ve böylece yukarıda bahsedilen bu izlemesi zor çalışma zamanı serileştirme hatalarını alamazsınız.

Ancak otomatik olarak oluşturulan kimlik stratejisinin bir arka tarafı vardır. Yani aynı sınıf için oluşturulan kimlikler derleyiciler arasında farklılık gösterebilir (yukarıda Jon Skeet tarafından belirtildiği gibi). Bu nedenle, farklı derleyicilerle derlenen kod arasında serileştirilmiş veriler iletirseniz, kimlikleri yine de manuel olarak tutmanız önerilir.

Bahsedilen ilk kullanım durumunda olduğu gibi verilerinizle geriye dönük olarak uyumluysanız, muhtemelen kimliği kendiniz de korumak istersiniz. Bu, okunabilir kimlikleri almak ve ne zaman ve nasıl değiştikleri üzerinde daha fazla kontrole sahip olmak için.


4
Geçici olmayan alanların eklenmesi veya çıkarılması, sınıf serileştirme ile uyumsuz olmasını sağlamaz. Bu nedenle, bu tür değişikliklere 'çarpmak' için bir neden yoktur.
user207421

4
@EJP: Ha? Veri eklemek dünyamdaki serileştirme verilerini kesinlikle değiştiriyor.
Alexander Torstling

3
@AlexanderTorstling Yazdıklarımı oku. 'Serileştirme verilerini değiştirmediğini' söylemedim. 'Sınıf serileştirmesini uyumsuz yapmaz' dedim. Aynı şey değil. Nesne Serileştirme Spesifikasyonunun Sürüm Oluşturma bölümünü okumanız gerekir.
user207421

3
@EJP: Geçici olmayan bir alan eklemenin zorunlu olarak sınıf serileştirmesini uyumsuz yaptığınız anlamına gelmediğini, ancak serileştirilmiş verileri değiştiren yapısal bir değişiklik olduğunu ve bunu yaparken genellikle sürümü çarpıştırmak istediğinizi anlıyorum. daha sonra da açıklayacağım geriye dönük uyumluluğu ele alacağım. Tam olarak ne demek istiyorsun?
Alexander Torstling

4
Demek istediğim tam olarak söylediğim gibi. Geçici olmayan alanlar eklemek veya kaldırmak, Serialization sınıfını uyumsuz hale getirmez. Bu nedenle, her yaptığınızda serialVersionUID öğesini çarpmanız gerekmez.
user207421

72

SerialVersionUID nedir ve neden kullanmalıyım?

SerialVersionUIDher sınıf için benzersiz bir tanımlayıcıdır, JVMSerileştirme sırasında Serileştirme sırasında aynı sınıfın kullanılmasını sağlayan sınıfın sürümlerini karşılaştırmak için kullanır.

Birini belirtmek daha fazla kontrol sağlar, ancak JVM belirtmezseniz bir tane oluşturur. Üretilen değer farklı derleyiciler arasında farklılık gösterebilir. Ayrıca, bazen sadece bazı nedenlerden dolayı eski serileştirilmiş nesnelerin serileştirilmesini yasaklamak istersiniz [ backward incompatibility] ve bu durumda serialVersionUID'yi değiştirmeniz gerekir.

İçin JavadocsSerializable söz hakkından :

varsayılan serialVersionUID hesaplaması, derleyici uygulamalarına bağlı olarak değişebilen sınıf ayrıntılarına karşı oldukça duyarlıdır ve bu nedenle InvalidClassExceptionserileştirme sırasında beklenmedik durumlara neden olabilir .

Bu nedenle, serialVersionUID değerini bildirmeniz gerekir çünkü bize daha fazla kontrol sağlar .

Bu makalenin konuyla ilgili bazı iyi noktaları var.


3
@Vinothbabu ama serialVersionUID statiktir, bu nedenle statik değişkenler serileştirilemez. o zaman nasıl jvm, serileştirme nesnesinin sürümünün ne olduğunu bilmeden sürümü kontrol edecektir
Kranthi Sama

3
Bu cevapta belirtilmeyen tek şey, nedenini serialVersionUIDbilmeden körü körüne dahil ederek istenmeyen sonuçlara neden olabilmenizdir . Tom Anderson'ın MetroidFan2002'nin cevabı hakkındaki yorumu şu şekildedir: "Kalıcı depolama için serileştirme kullanmıyorsanız, değer eklemek yerine @SuppressWarnings kullanmanız gerektiğini söyleyebilirim. Sınıfı daha az karmaşık hale getirir ve serialVersionUID mekanizması uyumsuz değişikliklere karşı sizi korur. "
Kirby

7
serialVersionUIDolduğu değil bir 'her sınıf için benzersiz bir tanımlayıcı'. Tam nitelikli sınıf adı şudur. Bir sürüm göstergesidir.
user207421

58

Orijinal soru, bunun neden Serial Version IDyararlı olabileceğini 'neden önemli' ve 'örnek' istedi . Bir tane buldum.

Bir Carsınıf oluşturduğunuzu , onu başlattığınızı ve bir nesne akışına yazdığınızı varsayalım. Düzleştirilmiş araba nesnesi bir süre dosya sisteminde oturur. Bu arada, Carsınıf yeni bir alan eklenerek değiştirilirse. Daha sonra, düzleştirilmiş Carnesneyi okumaya (yani serisini kaldırmaya) çalıştığınızda java.io.InvalidClassException- elde edersiniz - çünkü tüm serileştirilebilir sınıflara otomatik olarak benzersiz bir tanımlayıcı verilir. Bu istisna, sınıfın tanımlayıcısı düzleştirilmiş nesnenin tanımlayıcısına eşit olmadığında atılır. Gerçekten düşünürseniz, yeni alanın eklenmesi nedeniyle istisna atılır. Açık bir serialVersionUID bildirerek sürümlendirmeyi kendiniz denetleyerek bu özel durumun atılmasını önleyebilirsiniz. Açık bir şekilde beyan etmede küçük bir performans avantajı da vardır.serialVersionUID(çünkü hesaplanması gerekmez). Bu nedenle, Serializable sınıflarınıza aşağıda gösterildiği gibi oluşturduğunuz anda kendi serialVersionUID öğenizi eklemek en iyi yöntemdir:

public class Car {
    static final long serialVersionUID = 1L; //assign a long value
}

Ve her UID'ye 1L değil rastgele uzun bir sayı atanmalıdır.
abbas

4
@abbas 'Biri' bunu yapmalı neden? Lütfen ne fark yarattığını açıklayınız.
user207421

Adından da anlaşılacağı gibi, nesneyi serileştirmek için kullanılan sınıfın sürümünü temsil eder. Her seferinde aynı numarayı atarsanız, seri numarasını kaldırmak için doğru sınıfı bulamazsınız. Sınıfta her değişiklik yaptığınızda, sürümü de değiştirmek daha iyidir.
abbas

2
@abbas, bu niyet doğal sayıları arttırmak 1vb. ile çatışmaz .
Vadzim

2
@BillK, serileştirme kontrol sınıf adı ve serialVersionUID çifti bağlı olduğunu düşündüm. Farklı sınıfların ve kütüphanelerin farklı numaralandırma şemaları hiçbir şekilde karışamaz. Yoksa kod üreten kütüphaneler mi ima ettiniz?
Vadzim

44

Önce serileştirmenin ne olduğunu açıklamam gerekiyor.

Serileştirme , bir nesneyi ağ üzerinden göndermek için bir nesneyi bir akışa dönüştürmeye VEYA Dosyaya kaydet VEYA harf kullanımı için DB'ye kaydetmeye izin verir.

Serileştirme için bazı kurallar vardır .

  • Bir nesne yalnızca sınıfı veya üst sınıfı Serializable arabirimini uyguladığında serileştirilebilir

  • Bir nesne, üst sınıfı olmasa bile serileştirilebilirdir (kendisi Serializable arabirimini uygular). Ancak, Serileştirilebilir arabirimi uygulamayan, serileştirilebilir sınıf hiyerarşisindeki ilk üst sınıf bir arg-no yapıcısına sahip OLMAMALIDIR. Bu ihlal edilirse, readObject () yöntemi çalışma zamanında bir java.io.InvalidClassException oluşturur

  • Tüm ilkel tipler serileştirilebilir.

  • Geçici alanlar (geçici değiştiriciyle) serileştirilmez (yani kaydedilmez veya geri yüklenmez). Serializable uygulayan bir sınıf, serileştirmeyi desteklemeyen sınıfların geçici alanlarını işaretlemelidir (örneğin, bir dosya akışı).

  • Statik alanlar (statik değiştiricili) serileştirilmez.

Ne zaman Objecttefrika edilir Java Runtime, seri sürüm numarası aka ilişkilendirir serialVersionID.

SerialVersionID'ye ihtiyacımız olduğunda: Gönderen ve alıcının serileştirme ile uyumlu olduğunu doğrulamak için serisini kaldırma işlemi sırasında. Alıcı sınıfa farklı bir yükserialVersionIDeklediyse, seriyi kaldırma işlemi sona ererInvalidClassCastException.
Serileştirilebilir bir sınıf,statik, son ve uzun bir tür olması gerekenserialVersionUIDbir alan bildirerekkendiliğindenaçıkçabildirebilirserialVersionUID.

Bunu bir örnekle deneyelim.

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();
}
}

Seri Nesne Oluştur

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");
}
}

Nesnenin serisini kaldırma

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());
 }
}    

NOT: Şimdi Employee sınıfının serialVersionUID değerini değiştirin ve kaydedin:

private static final long serialVersionUID = 4L;

Ve Reader sınıfını yürütün. Writer sınıfını yürütmemek için bir istisna elde edersiniz.

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)

Yanılıyorsam beni düzeltin - yerel sınıf, şu anda sınıf yolunda olan / kullandığınız sınıftır ve akış, başka bir tarafça kullanılan örnektir (örneğin, size bir yanıt döndüren ve seri hale getirilmiş bir sunucu). tepki). Bu durumu, üçüncü taraf kütüphanelerini güncelleyen bir sunucuyla iletişim kurarken karşılaşabilirsiniz, ancak siz (istemci) bunu yapmadınız.
Victor

37

Nesnelerinizi bayt dizisine serileştirmeniz ve göndermeniz / depolamanız gerekmeyecekse, endişelenmenize gerek yoktur. Bunu yaparsanız, nesnenin serileştiricisi onu sınıf yükleyicisinin sahip olduğu nesnenin sürümüyle eşleştireceğinden serialVersionUID'nizi göz önünde bulundurmalısınız. Bununla ilgili daha fazla bilgiyi Java Dil Spesifikasyonu'nda bulabilirsiniz.


10
Nesneleri serileştirmeyecekseniz, neden Serileştirilebilirler?
erickson

7
@erickson - üst sınıf, örneğin ArrayList serileştirilebilir olabilir, ancak kendi nesnenizin (örneğin, değiştirilmiş bir dizi listesi) onu bir taban olarak kullanmasını istiyorsunuz, ancak oluşturduğunuz Koleksiyonu serileştirmeyeceksiniz.
MetroidFan2002

5
Java Dil Spesifikasyonu'nun hiçbir yerinde belirtilmemiştir. Nesne Sürüm Spesifikasyonu'nda belirtilmiştir.
user207421


34

Bu uyarıyı serileştirmeyi hiç düşünmediğiniz bir sınıfta alırsanız ve kendinizi beyan etmediyseniz implements Serializable, bunun nedeni genellikle Serializable'ı uygulayan bir üst sınıftan miras almış olmanızdır. Çoğu zaman miras kullanmak yerine böyle bir nesneye delege etmek daha iyi olur.

Yani, yerine

public class MyExample extends ArrayList<String> {

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

yapmak

public class MyExample {
    private List<String> myList;

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

ve ilgili yöntemlerde (veya ) myList.foo()yerine çağırın . (Bu her durumda uygun değildir, ancak yine de oldukça sıktır.)this.foo()super.foo()

Sık sık JFrame veya benzeri şeyleri genişleten insanlar görüyorum, gerçekten sadece buna yetki vermeleri gerekiyor. (Bu, bir IDE'de otomatik tamamlama için de yardımcı olur, çünkü JFrame, sınıfınızda özel olanları çağırmak istediğinizde ihtiyacınız olmayan yüzlerce yöntem içerir.)

Uyarının (veya serialVersionUID) kaçınılmaz olduğu bir durum, normalde anonim bir sınıfta, yalnızca actionPerformed yöntemini ekleyerek AbstractAction'dan genişlettiğiniz durumdur. Bu durumda bir uyarı olmaması gerektiğini düşünüyorum (çünkü normalde bu tür anonim sınıfları sınıfınızın farklı sürümlerinde serileştirip serileştiremezsiniz), ancak derleyicinin bunu nasıl tanıyabileceğinden emin değilim.


4
Özellikle ArrayList gibi sınıfları tartışırken, miras üzerine kompozisyonun daha anlamlı olduğunu düşünüyorum. Bununla birlikte, birçok çerçeve insanların serileştirilebilen soyut üst sınıflardan (Struts 1.2'nin ActionForm sınıfı veya Saxon'un ExtensionFunctionDefinition gibi) genişlemesini gerektirir, bu durumda bu çözüm mümkün değildir. Haklısın, bazı durumlarda uyarı göz ardı edilirse iyi olurdu (soyut bir serileştirilebilir sınıftan
uzanıyormuş gibi

2
Şüphesiz, bir sınıfı üye olarak eklemek yerine miras almak isterseniz, kullanmak istediğiniz üye sınıfının HER yöntemi için çok sayıda durumda olanaksız hale getirecek bir sarmalayıcı yöntemi yazmanız gerekir. Java'nın __AUTOLOADbilmediğim perl'lere benzer bir işlevi yoksa.
M_M

4
@ M_M: Kaydırılan nesneye çok sayıda yöntem delege atadığınızda, elbette temsilci seçme uygun olmaz. Ancak bu durumun bir tasarım hatasının işareti olduğunu varsayalım - sınıfınızın kullanıcılarının (örn. "MainGui"), sarılmış nesnenin (örneğin JFrame) birçok yöntemini çağırması gerekmez.
Paŭlo Ebermann

1
Delegasyonla ilgili sevmediğim, delege için bir referans tutma gereğidir. Ve her referans daha fazla hafıza demektir. Yanlışsam düzelt. 100 nesneden bir CustomisedArrayList gerekiyorsa o zaman bu çok önemli değil ama birkaç nesnenin yüzlerce CustomizdeArrayList gerekiyorsa o zaman bellek kullanımı önemli ölçüde artar.
WVrock

2
Atılabilir serileştirilebilir ve yalnızca Atılabilir atılabilirdir, bu nedenle serileştirilemeyen bir istisna tanımlamak mümkün değildir. Yetki devri mümkün değil.
Phil

22

SerialVersionUID alanının önemini anlamak için, Serileştirme / Diziselleştirmenin nasıl çalıştığını anlamak gerekir.

Serializable sınıf nesnesi serileştirildiğinde Java Runtime, seri numarası (seriVersionUID olarak adlandırılır) bu serileştirilmiş nesne ile ilişkilendirir. Bu serileştirilmiş nesnenin serisini kaldırdığınızda, Java Runtime serileştirilmiş nesnenin serialVersionUID'sini sınıfın serialVersionUID değeriyle eşleştirir. Her ikisi de eşitse, yalnızca serisini kaldırma işlemiyle devam eder, başka InvalidClassException oluşturur.

Bu nedenle, Serileştirme / Deserialization işlemini başarılı kılmak için serileştirilmiş nesnenin serialVersionUID değerinin sınıfın serialVersionUID değerine eşdeğer olması gerektiği sonucuna varıyoruz. Programlayıcının programda serialVersionUID değerini açıkça belirtmesi durumunda, serileştirme ve serileştirme platformuna bakılmaksızın aynı değer serileştirilmiş nesne ve sınıfla ilişkilendirilecektir (örn. Serileştirme, pencereler gibi platform üzerinde sun veya MS JVM ve Deserialization Zing JVM kullanan farklı platform Linux'ta olabilir).

Ancak serialVersionUID'nin programcı tarafından belirtilmemesi durumunda, herhangi bir nesnenin Serialization \ DeSerialization işlemi sırasında Java çalışma zamanı bunu hesaplamak için kendi algoritmasını kullanır. Bu serialVersionUID hesaplama algoritması bir JRE'den diğerine değişir. Nesnenin serileştirildiği ortamın bir JRE (örn: SUN JVM) kullanıyor olması ve serileştirmenin gerçekleştiği ortamın Linux Jvm (zing) kullanıyor olması da mümkündür. Bu gibi durumlarda, serileştirilmiş nesne ile ilişkili serialVersionUID, serileştirme ortamında hesaplanan serialVersionUID sınıfından farklı olacaktır. Buna karşılık serileştirme başarılı olmayacak. Bu tür durumları / sorunları önlemek için programcı her zaman Serializable sınıfının serialVersionUID değerini belirtmelidir.


2
Algoritma değişmez, ancak biraz az belirtilmiştir.
user207421

... algoritma değişmez, ancak biraz az belirtilmiştir ... yani herhangi bir jvm değişebilir ..... @ user207421
AnthonyJClink

18

Rahatsız etmeyin, varsayılan hesaplama gerçekten iyi ve vakaların% 99,9999'u için yeterli. Sorunlarla karşılaşırsanız, - daha önce de belirtildiği gibi - ihtiyaç duyuldukça UID'leri tanıtabilirsiniz (ki bu pek olası değildir)


2
Çöp. Sınıfın değişmemesi durumunda yeterlidir. '% 99,9999'u destekleyecek sıfır kanıtınız var.
Kullanıcı207421

18

Eksik serialVersionUID öğesinin soruna neden olabileceği bir örneğe gelince:

Bir EJBmodül kullanan bir Web modülünden oluşan bu Java EE uygulaması üzerinde çalışıyorum . Web modülü EJBmodülü uzaktan çağırır ve bağımsız değişken olarak POJOuygulanan bir modülü geçirir Serializable.

Bu POJO'ssınıf EJB kavanozunun içinde ve web modülünün WEB-INF / lib içindeki kendi kavanozunda paketlenmiştir. Aslında aynı sınıflar, ama EJB modülünü paketlediğimde, bu POJO'nun kavanozunu EJB modülü ile birlikte paketlemek için paketinden çıkarıyorum.

Onun çağrısı EJBaşağıdaki istisna ile başarısız oldu çünkü ben ilan etmedi 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

16

Genelde serialVersionUIDtek bir bağlamda kullanıyorum: Bildiğimde Java VM'nin bağlamından çıkacak.

Bunu ne zaman kullanacağım ObjectInputStreamve ObjectOutputStreambaşvurum için ya da kullandığım bir kütüphane / çerçeve bildiğim zaman bunu bilirdim. SerialVersionID, farklı sürümlerdeki farklı Java VM'lerinin veya satıcıların doğru şekilde çalışmasını sağlar veya VM'nin dışında depolanır ve alınırsa HttpSession, oturum verileri uygulama sunucusunun yeniden başlatılması ve yükseltilmesi sırasında bile kalabilir.

Diğer tüm durumlar için kullanıyorum

@SuppressWarnings("serial")

çünkü çoğu zaman varsayılan serialVersionUIDdeğer yeterlidir. Bunlar arasında Exception, HttpServlet.


Değiştirilebilecekleri kaplarda HttpServlet veya örneğin RMI'da İstisna içermez.
user207421

14

Alan verileri, sınıfta depolanan bazı bilgileri temsil eder. Sınıf Serializablearabirimi uygular , böylece tutulma serialVersionUIDalanı bildirmek için otomatik olarak sunulur . Orada ayarlanan 1 değeri ile başlayalım.

Bu uyarının gelmesini istemiyorsanız şunu kullanın:

@SuppressWarnings("serial")

11

CheckStyle'ın Serializable uygulayan bir sınıfın serialVersionUID değerinin iyi bir değere sahip olup olmadığını doğrulaması iyi olur, yani seri sürüm kimliği üretecinin üreteceği değerle eşleşir. Örneğin, çok sayıda serileştirilebilir DTO'ya sahip bir projeniz varsa, mevcut serialVersionUID'yi silmeyi ve yeniden oluşturmayı hatırlamak bir acıdır ve şu anda bunu doğrulamanın tek yolu her sınıf için yeniden oluşturmak ve karşılaştırmaktır. eski olan. Bu çok çok acı verici.


8
SerialVersionUID öğesini her zaman jeneratörün üreteceği değere ayarlarsanız, buna gerçekten ihtiyacınız yoktur. Sonuçta, onun varoluş nedeni, sınıf hala uyumlu olduğunda, değişikliklerden sonra aynı kalmaktır.
Paŭlo Ebermann

4
Bunun nedeni, farklı derleyicilerin aynı sınıf için aynı değeri bulmasıdır. Javadoc'larda açıklandığı gibi (yukarıda da cevaplanmıştır), üretilen versiyon kırılgandır ve sınıf düzgün bir şekilde serileştirilebilir olsa bile değişebilir. Bu testi her defasında aynı derleyicide yaptığınız sürece güvenli olmalıdır. jdk'yi yükseltirseniz ve kod değişmese bile yeni bir kural ortaya çıkarsa tanrı size yardımcı olur.
Andrew Backer

2
Üretebilecekleri eşleştirmek gerekli değildir serialver. -1
user207421

Genel olarak hiç gerekli değildir. @ AndrewBacker'ın davası, aynı .java dosyasında iki farklı derleyici gerektirir. .Class dosyalarının her iki sürümü de birbiriyle iletişim kurar - çoğu zaman sadece sınıfı oluşturup dağıtırsınız. Eğer durum buysa, bir SUID'ye sahip olmamak işe yarayacaktır.
Bill K

1
Serialization'u gerçekten depolama / alma amacıyla kullanan kişiler genellikle serialVersionUID1 olarak ayarlayacaktır. Sınıfın daha yeni bir sürümü uyumlu değilse, ancak yine de eski verileri işleyebilmeniz gerekiyorsa, sürüm numarasını artırır ve eski biçimlerle uğraşmak. serialVersionUIDRastgele bir sayı (işe yaramaz) olduğu veya sınıfın görünüşe göre 10'dan fazla farklı sürümle uğraşması gerektiğinden 1 basamaktan daha büyük gördüğümde ağlıyorum .
john16384

11

SerialVersionUID, nesnenin sürüm kontrolü için kullanılır. sınıf dosyanızda serialVersionUID değerini de belirtebilirsiniz. SerialVersionUID belirtmemenin bir sonucu olarak, sınıftaki herhangi bir alanı eklediğinizde veya değiştirdiğinizde, yeni bir sınıf ve eski serileştirilmiş nesne için oluşturulan serialVersionUID'nin farklı olacağı için zaten serileştirilmiş sınıf kurtarılamayacaktır. Java serileştirme işlemi serileştirilmiş nesnenin durumunu kurtarmak için doğru serialVersionUID'ye dayanır ve serialVersionUID uyuşmazlığı durumunda java.io.InvalidClassException özel durumunu atar

Daha fazla bilgi için: http://javarevisited.blogspot.com/2011/04/top-10-java-serialization-interview.html#ixzz3VQxnpOPZ


9

Java'da neden sınıf SerialVersionUIDiçi kullanıyorsunuz Serializable?

Sırasında serialization, Java çalışma zamanı bir sınıf için sürüm numarası oluşturur, böylece daha sonra seri serisini kaldırabilir. Bu sürüm numarası SerialVersionUIDJava'da bilinir .

SerialVersionUIDserileştirilmiş verileri sürümlemek için kullanılır. Bir sınıfın serisini yalnızca SerialVersionUIDserileştirilmiş örnekle eşleşiyorsa serileştirebilirsiniz. SerialVersionUIDSınıfımızda beyan etmediğimizde , Java çalışma zamanı bunu bizim için üretir, ancak önerilmez. İlan etmek önerilir SerialVersionUIDolarak private static final longvarsayılan mekanizma önlemek için değişken.

Bir sınıfı Serializableişaretleyici arabirimi uygulayarak bildirdiğinizde java.io.Serializable, Java çalışma zamanı, Externalizablearabirimi kullanarak işlemi özelleştirmediyseniz, varsayılan Serileştirme mekanizmasını kullanarak bu sınıfın örneğini diske kaydeder .

ayrıca bkz . Java'daki Serializable sınıfında neden SerialVersionUID kullanılır?

Kodu: javassist.SerialVersionUID


8

Eski sınıflarla uyumluluğu korurken, serialVersionUID ayarlanmamış çok sayıda sınıfta değişiklik yapmak istiyorsanız, IntelliJ Idea, Eclipse gibi araçlar rastgele sayılar ürettiklerinden ve bir grup dosyada çalışmadığından kısa sürede düşer tek seferde. SeriVersionUID sorununu kolaylıkla değiştirmek için aşağıdaki bash betiğini (Windows kullanıcıları için özür dilerim, Mac satın almayı veya Linux'a dönüştürmeyi düşünün) geldim:

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

Bu betiği kaydedin, add_serialVersionUID.sh dosyasını size ~ / bin olarak söyleyin. Sonra Maven veya Gradle projenizin kök dizininde çalıştırın:

add_serialVersionUID.sh < myJavaToAmend.lst

Bu .lst, serialVersionUID öğesini aşağıdaki biçimde eklemek için java dosyalarının listesini içerir:

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

Bu komut dosyası başlık altında JDK serialVer aracını kullanır. Bu yüzden $ JAVA_HOME / bin'inizin PATH içinde olduğundan emin olun.


2
Bana bir fikir verir: Seri sürümü kullanıcı kimliğini her zaman böyle bir araçla, asla elle, bir sürüm yapmadan önce yeniden oluşturun - bu şekilde, seri sürümü kullanıcı kimliği gerçek olması nedeniyle değişmesi gereken bir sınıfta değişiklik yapmayı unutmamanız gerekir uyumsuz değişiklik. Bunu manuel olarak takip etmek çok zordur.
Ignazio

6

Bu soru Etkili Java'da Joshua Bloch tarafından çok iyi belgelenmiştir. Çok iyi bir kitap ve bir zorunluluktur okuyun. Aşağıdaki nedenlerden bazılarını anlatacağım:

Serileştirme çalışma zamanı, serileştirilebilir her sınıf için Seri sürüm adı verilen bir sayı ile gelir. Bu sayıya serialVersionUID adı verilir. Şimdi bu sayının arkasında bazı Matematik var ve sınıfta tanımlanan alanlara / yöntemlere göre ortaya çıkıyor. Aynı sınıf için her seferinde aynı sürüm oluşturulur. Bu sayı, serileştirme sırasında serileştirilmiş bir nesnenin göndericisinin ve alıcısının, serileştirme ile uyumlu olan bu nesne için yüklü sınıflara sahip olduğunu doğrulamak için kullanılır. Alıcı, karşılık gelen gönderenin sınıfından farklı bir serialVersionUID değerine sahip nesne için bir sınıf yüklediyse, serileştirme işlemi InvalidClassException özelliğine neden olur.

Sınıf serileştirilebiliyorsa, kendi serialVersionUID öğenizi statik, son ve uzun tipte olması gereken "serialVersionUID" adlı bir alanı bildirerek de açıkça bildirebilirsiniz. Çoğu IDE Eclipse gibi uzun dizeleri oluşturmanıza yardımcı olur.


6

Bir nesne serileştirildiğinde, nesnenin sınıfı için bir sürüm kimlik numarası ile damgalanır.Bu kimliğe serialVersionUID adı verilir ve sınıf yapısı hakkındaki bilgilere dayanarak hesaplanır. Bir Employee sınıfı yaptığınızı ve bunun #333 (JVM tarafından atanan) sürüm kimliğine sahip olduğunu varsayalım.

Bir durum düşünün - gelecekte sınıfınızı düzenlemeniz veya değiştirmeniz gerekiyor ve bu durumda JVM ona yeni bir UID atayacaktır (varsayalım # 444). Şimdi çalışan nesnesinin serisini kaldırmaya çalıştığınızda, JVM serileştirilmiş nesnenin (Çalışan nesnesi) sürüm kimliğini (# 333) sınıfınkiyle karşılaştırır, yani # 444 (Değiştirildiğinden beri). Karşılaştırmada JVM her iki sürüm UID'sinin farklı olduğunu ve dolayısıyla Deserialization başarısız olacağını görecektir. Bu nedenle, her sınıf için serialVersionID, programcının kendisi tarafından tanımlanırsa. Sınıf gelecekte geliştirilse bile aynı olacaktır ve bu nedenle JVM, sınıf değiştirilse bile sınıfın serileştirilmiş nesneyle her zaman uyumlu olduğunu görecektir. Daha fazla bilgi için HEAD FIRST JAVA bölüm 14'e bakabilirsiniz.


1
Her sınıfı bir nesnenin seri hale serialVersionUIDiletilir. Her nesneyle gönderilmez.
user207421

3

Basit Bir Açıklama:

  1. Verileri serileştiriyor musunuz?

    Serileştirme temel olarak sınıf verilerini bir dosyaya / akışa / vb. Diziselleştirme, bu verileri bir sınıfa geri okuyor.

  2. Üretime geçmeyi düşünüyor musunuz?

    Sadece önemsiz / sahte verilerle bir şey test ediyorsanız, endişelenmeyin (doğrudan serileştirmeyi test etmiyorsanız).

  3. Bu ilk versiyon mu?

    Öyleyse ayarlayın serialVersionUID=1L.

  4. Bu ikinci, üçüncü, vb eşya versiyonu mu?

    Şimdi endişelenmelisin serialVersionUIDve derinlemesine bakmalısın.

Temel olarak, yazmanız / okumanız gereken bir sınıfı güncellediğinizde sürümü doğru şekilde güncellemezseniz, eski verileri okumaya çalıştığınızda bir hata alırsınız.


2

'serialVersionUID', serileştirme işlemi sırasında bir sınıfı benzersiz olarak tanımlamak için kullanılan 64 bitlik bir sayıdır. Bir nesneyi serileştirdiğinizde, sınıfın serialVersionUID değeri de dosyaya yazılır. Bu nesnenin serisini kaldırdığınızda, java çalışma süresi serileştirilmiş verilerden bu serialVersionUID değerini ayıklar ve sınıfla ilişkilendirilen aynı değeri karşılaştırır. Her ikisi de eşleşmezse, 'java.io.InvalidClassException' atılır.

Serileştirilebilir sınıf açıkça bir serialVersionUID bildirmezse, serileştirme çalışma zamanı, sınıfın alanlar, yöntemler vb. Gibi çeşitli yönlerine dayalı olarak serialVersionUID değerini hesaplar. ,, Demo uygulaması için bu bağlantıya başvurabilirsiniz .


1

Uzun lafın kısasını anlatmak için bu alan serileştirilmiş verilerin doğru şekilde serileştirilip atılamayacağını kontrol etmek için kullanılır. Serileştirme ve serileştirme genellikle programın farklı kopyaları tarafından yapılır - örneğin sunucu nesneyi dizeye dönüştürür ve istemci alınan dizeyi nesneye dönüştürür. Bu alan, her ikisinin de bu nesnenin ne olduğu hakkında aynı fikirle çalıştığını söyler. Bu alan şu durumlarda yardımcı olur:

  • programınızın farklı yerlerde (1 sunucu ve 100 istemci gibi) birçok farklı kopyası var. Nesnenizi değiştirirseniz, sürüm numaranızı değiştirirseniz ve bu istemcilerden birini güncellemeyi unutursanız, seriyi kaldıramayacağını bilir.

  • verilerinizi bir dosyada sakladınız ve daha sonra, değiştirilmiş nesne ile programınızın güncellenmiş sürümü ile açmaya çalışın - sürümünüzü doğru tutarsanız bu dosyanın uyumlu olmadığını bileceksiniz

Ne zaman önemlidir?

En açık olanı - nesnenize bazı alanlar eklerseniz, eski sürümler nesne yapılarında bu alanlara sahip olmadıkları için bunları kullanamazlar.

Daha az belirgin - Nesnenin serileştirmesini kaldırdığınızda, dizede bulunmayan alanlar NULL olarak saklanır. Alanınızı nesnenizden kaldırdıysanız, eski sürümler bu alanı her zaman NULL olarak tutar ve eski sürümler bu alandaki verilere güvenirse hatalı davranışa yol açabilir (yine de yalnızca eğlence için değil, bir şey için oluşturdunuz :-))

En az belirgin - Bazen bir alanın anlamına koyduğunuz fikri değiştirirsiniz. Örneğin, 12 yaşındayken "bisiklet" altında "bisiklet" demek istersiniz, ama 18 yaşında "motosiklet" demek istersiniz - arkadaşlarınız sizi "şehir genelinde bisiklete binmeye" davet ederse ve siz sadece bisiklet geldi, alanlar arasında aynı anlamı tutmanın ne kadar önemli olduğunu anlayacaksınız :-)


1

Öncelikle sorunuzu cevaplamak için, sınıfımızda SerialVersionUID'yi açıklamadığımızda, Java çalışma zamanı bunu bizim için üretir, ancak bu işlem alan sayısı, alan türü, alanların erişim değiştiricisi, uygulanan arayüz de dahil olmak üzere birçok sınıf meta verilerine duyarlıdır. Bu nedenle bunu kendimiz ilan etmeniz tavsiye edilir ve Eclipse sizi aynı konuda uyarır.

Serileştirme: Sıklıkla durumu (nesnenin değişkenlerindeki veriler) o kadar önemli olan önemli nesnelerle çalışırız; nesne durumunu diğerine göndermek durumunda güç / sistem arızaları (veya) ağ arızaları nedeniyle kaybetme riskini alamazız makinesi. Bu sorunun çözümü, yalnızca verilerin kalıcı (tutulması / kaydedilmesi) anlamına gelen "Kalıcılık" olarak adlandırılır. Serileştirme, kalıcılık elde etmenin birçok yolundan biridir (verileri diske / belleğe kaydederek). Nesnenin durumunu kaydederken, nesneyi düzgün bir şekilde okuyabilmek (serileştirme) için bir kimlik oluşturmak önemlidir. Bu benzersiz tanımlama kimliği SerialVersionUID'dir.


0

SerialVersionUID nedir? Cevap: - Diyelim ki biri Genel Merkezden diğeri ODC'den iki kişi var, her ikisi de sırasıyla serileştirme ve serileştirme yapacak. Bu durumda, ODC'de bulunan alıcının kimliği doğrulanmış kişi olduğunu doğrulamak için JVM, SerialVersionUID olarak bilinen Benzersiz bir Kimlik oluşturur.

İşte senaryoya dayanan güzel bir açıklama,

Neden SerialVersionUID?

Serileştirme : Serileştirme sırasında, her nesne gönderen tarafı ile JVM Benzersiz bir Tanımlayıcı kaydedecektir. JVM, gönderen sisteminde bulunan ilgili .class dosyasına dayanarak bu benzersiz kimliği oluşturmaktan sorumludur.

Deserialization : Deserialization sırasında, alıcı tarafı JVM, Object ile ilişkili benzersiz kimliği yerel sınıf Unique ID ile karşılaştıracaktır; yani JVM, alıcı sisteminde mevcut olan ilgili .class dosyasına dayalı olarak Unique ID yaratacaktır. Her iki benzersiz kimlik de eşleşirse, yalnızca serileştirme gerçekleştirilir. Aksi takdirde InvalidClassException diyerek Çalışma Zamanı İstisnası alırız. Bu benzersiz Tanımlayıcı, SerialVersionUID'den başka bir şey değildir

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.