Soru SerialVersionUID nedir ve neden kullanmalıyım?


Eclipse, uyarıları bir serialVersionUID kayıp.

Seri hale getirilebilir sınıf Foo, statik bir final bildirmez   uzun tipi serialVersionUID alanı

Nedir serialVersionUID ve neden önemli? Lütfen eksik olan bir örneği göster serialVersionUID bir soruna neden olur.


2489
2017-11-12 23:24


Menşei


Basit bir örnek mkyong.com/java-best-practices/understand-the-serialversionuid - Gopinagh.R


Cevaplar:


İçin dokümanlar java.io.Serializable Muhtemelen alacağınız kadar iyi bir açıklama var:

Serileştirme çalışma zamanı ilişkilendiricileri   her seri hale getirilebilir sınıf ile bir versiyon   serialVersionUID adı verilen numara   seri halterizasyon sırasında kullanılır   Gönderen ve alıcıyı doğrulamak için   bir seri hale getirilmiş nesnenin yüklendi   Bu nesne için sınıflar   ile uyumlu   serileştirme. Alıcı varsa   sahip olan nesne için bir sınıf yüklendi   bundan farklı bir serialVersionUID   karşılık gelen gönderenin sınıfının   daha sonra seri hale getirme    InvalidClassException. Bir seri hale getirilebilir   sınıf kendi ilan edebilir   serialVersionUID tarafından açıkça   adında bir alanın bildirilmesi   "serialVersionUID"bu olmalı   statik, son ve tür long:

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

Eğer bir   serialize sınıf açıkça değil   bir serialVersionUID bildirin, sonra   serialization runtime hesaplayacaktır   için varsayılan serialVersionUID değeri   Bu sınıfın çeşitli yönlerine dayanan   sınıfında açıklandığı gibi   Java (TM) Nesne Serileştirme   Şartname. Ancak öyle şiddetle   Tavsiye edilen tüm serileştirilebilir   sınıflar açıkça bildirir   serialVersionUID değerleri   varsayılan serialVersionUID hesaplama   sınıf detaylarına oldukça duyarlıdır   Bu derleyiciye bağlı olarak değişebilir   uygulamalar, ve sonuçta sonuçlanabilir   beklenmedik InvalidClassExceptions   serileştirme sırasında. Bu nedenle   tutarlılığı garanti etmek   genelinde serialVersionUID değeri   farklı java derleyicisi   uygulamalar, bir seri hale getirilebilir sınıf   açık beyan etmek zorundadır   serialVersionUID değeri. Ayrıca   açıkça tavsiye   serialVersionUID bildirimleri kullanır   Mümkün olduğunda, özel değiştirici   bu tür beyanlar sadece   hemen ilan etmek   class - serialVersionUID alanları değil   Kalıtsal üyeler olarak yararlıdır.


1911
2017-11-12 23:30



Öyleyse, söylediğiniz şey, eğer bir kullanıcı yukarıdaki tüm materyalleri anlamadıysa, bahsi geçen kullanıcı serileştirme konusunda endişelenmekten çekinmiyor mu? "Nasıl?" Diye cevapladın galiba. "Neden" açıklamak yerine. Birincisi, neden SerializableVersionUID ile uğraştığımı anlamıyorum. - Ziggy
Neden ikinci paragrafta: açıkça serialVersionUID belirtmezseniz, otomatik olarak bir değer oluşturulur - ancak derleyici uygulaması bağımlı olduğu için bu kırılgandır. - Jon Skeet
Ve Eclipse neden "özel statik son uzun serialVersionUID = 1L;" ihtiyacım var diyor Özel durum sınıfını genişletdiğimde? - JohnMerlino
@JohnMerlino: Sana söylemeyi beklemezdim gerek bir - ama olabilir düşündüren istisnaları doğru şekilde serileştirmenize yardımcı olmak için Onları serileştirmeyecekseniz, sabitliğe gerçekten ihtiyacınız yok. - Jon Skeet
@JohnMerlino, sorunun bir bölümünü neden cevaplamak için: İstisna uygular serilestirilebilir ve tutulma, bir seriVersionUID ayarlamamanız konusunda uyarır. Bu, JonSkeet'in gönderdiği sorunların önüne geçmek için iyi bir fikirdir (eğer dersi serileştirmezseniz). - zpon


Eğer serileştiriyorsanız, uygulama için seri hale getirmeniz gerekiyorsa (örneğin bir HTTPSession için serileştirdiğinizde kimin umurunda olursa olsun, eğer saklanırsa veya saklanmazsa, muhtemelen bir form nesnesinin serileştirilmesiyle ilgilenmezsiniz) sonra bunu görmezden gelebilirsiniz.

Eğer gerçekten serileştirme kullanıyorsanız, sadece seri hale getirme kullanarak nesneleri doğrudan depolamayı ve almayı planlıyorsanız önemlidir. SerialVersionUID, sınıf sürümünüzü temsil eder ve sınıfınızın geçerli sürümü önceki sürümüyle geriye dönük olarak uyumlu değilse, bunu artırmalısınız.

Çoğu zaman, seriyi doğrudan kullanamazsınız. Bu durumda, hızlı düzeltme seçeneğini tıklatarak varsayılan bir seri hale getirilebilir kullanıcı kimliği oluşturun ve bunun için endişelenmeyin.


415
2017-11-13 04:24



Kalıcı depolama için serileştirme kullanmıyorsanız, bir değer eklemek yerine @SuppressWarnings kullanmanız gerektiğini söyleyebilirim. Sınıfı daha az karmaşık hale getirir ve sizi uyumsuz değişikliklerden korumak için serialVersionUID mekanizmasının ortamını korur. - Tom Anderson
Bir satırı (@SuppressWarnings ek açıklaması) başka bir satıra (serileştirilebilir kimliğe) eklemenin "sınıfı daha az karıştırarak" nasıl eklediğini göremiyorum. Ve kalıcı depolama için serileştirme kullanmıyorsanız, neden sadece "1" kullanmıyorsunuz? Bu durumda otomatik olarak yeniden yaratılan kimliği umursamazsınız. - MetroidFan2002
@ MetroidFan2002: Bence TomAnderson'ın noktası serialVersionUID Sizi uyumsuz değişikliklerden korumak geçerlidir. kullanma @SuppressWarnings Kalıcı depolama için sınıfı kullanmak istemiyorsanız, niyetinizi daha iyi belgeler. - AbdullahC
"Sınıfınızın şu anki sürümü, önceki sürümüyle geriye dönük olarak uyumlu değilse, bunu artırmalısınız:" Serialization'un kapsamlı nesne sürümlendirme desteğini, (a) sınıfın gerçekten artık serileştirme-uyumsuz bir şekilde olduğundan emin olmak için, Spesifikasyona göre elde edilmesi oldukça zordur; (b) akışının uyumlu kaldığından emin olmak için özel read / writeObject () yöntemleri, readResolve / writeReplace () yöntemleri, serializableFields bildirimleri, vb. gibi bir şema denemek. Gerçek değiştirme serialVersionUID son çare, umutsuzluk müşaviri. - user207421
ClassVersionUID'nin @EJP artışı, sınıfın ilk yazarı açık bir şekilde tanıtıldığı zaman resme girer. Jvm, seri kimliği oluşturulduğunu söyleyebilirim. bu en iyisi Cevap serileştirme üzerinde gördüm. - overexchange


Josh Bloch'un kitabını takmak için bu fırsatı kaçırmayacağım. Etkili Java (2. Baskı). Bölüm 11, Java serileştirme konusunda 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 genel ve korunan üyelere dayalı olarak oluşturulur. Bunlardan herhangi birini herhangi bir şekilde değiştirmek serialVersionUID. Bu nedenle, sadece sınıfın bir versiyonunun serileştirilmeyeceğinden (süreçler arasında ya da daha sonra depodan kaldırıldığından) emin değilseniz, bunlarla uğraşmanıza gerek yoktur.

Şimdilik bunları görmezden gelirseniz ve sınıfı bir şekilde değiştirmeniz gerektiğine ancak sınıfın eski sürümüne uyum sağladığınızı fark ederseniz, JDK aracını kullanabilirsiniz. serialver üretmek için serialVersionUID üzerinde eski sınıf ve açıkça yeni sınıfta bunu ayarlayın. (Değişikliklerinize bağlı olarak, ekleyerek özel serileştirme de uygulamanız gerekebilir. writeObject ve readObject yöntemler - bkz. Serializable javadoc veya daha önce sözü edilen bölüm 11.)


264
2017-11-12 23:37



Birisi bir sınıfın eski sürümleri ile ilgili endişeler varsa SerializableVersionUID ile rahatsız olabilir? - Ziggy
Yup, daha yeni sürümün herhangi bir genel üye korunursa, varsayılan SerializableVersionUID farklı olacak ve bir InvalidClassExceptions yükseltir. - Chander Shivdasani
Sınıf adı, uygulanan arayüzler, tüm genel ve korunan yöntemler, TÜM örnek değişkenler. - Achow
Joshua Bloch'un bunun için tavsiyede olduğunu belirtmekte fayda var. her Seri hale getirilebilir sınıf, seri versiyonu uid'i belirtmeye değer. Bölüm 11'den alıntı: Hangi serileştirilmiş formu seçerseniz seçin, yazdığınız her seri hale getirilebilir sınıfta açık bir seri sürüm UID bildirin. Bu, seri versiyon UID'yi potansiyel bir uyumsuzluk kaynağı olarak ortadan kaldırır (Madde 74). Küçük bir performans avantajı da var. Seri versiyon UID sağlanmamışsa, çalışma zamanında bir tane üretmek için pahalı bir hesaplama gerekir. - Ashutosh Jindal


Eclipse'e bu serialVersionUID uyarılarını dikkate almamalarını söyleyebilirsin:

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

Bilmediyseniz, bu bölümde etkinleştirebileceğiniz başka birçok uyarı vardır (hatta bazıları hata olarak bildirilmiştir), birçoğu çok faydalıdır:

  • Potansiyel Programlama Sorunları: Olası yanlışlıkla boolean atama
  • Potansiyel Programlama Sorunları: Boş gösterici erişimi
  • Gereksiz kod: Yerel değişken hiç okunmuyor
  • Gereksiz kod: Gereksiz boş çek
  • Gereksiz kod: Gereksiz döküm veya 'instanceof'

ve daha fazlası.


124
2017-11-13 01:17



ama sadece orijinal posterin herhangi bir şeyi serileştirdiği görünmüyor. Poster "bu şeyi serileştiriyorum" dediyse, o zaman bunun yerine bir oy hakkı alacaksın: P - John Gardner
Doğru - Sorgunun sadece uyarılmak istemediğini varsayıyordum - matt b
@Gardner -> kabul etti! Ancak, sorgulayıcı, neden uyarılmak istemeyeceğini de bilmek istiyor. - Ziggy
Sorgucu, neden bir UID'nin olması gerektiği konusunda ümit vericidir. Bu yüzden sadece onu uyarmaktan vazgeçtiğini söyleyerek reddedilmeli. - cinqS


serialVersionUID seri hale getirilmiş verilerin versiyonlamasını kolaylaştırır. Serileştirme sırasında değeri verilerle birlikte saklanır. Seri hale getirilmediğinde, serileştirilmiş verilerin mevcut kodla nasıl eşleştiğini görmek için aynı sürüm kontrol edilir.

Verilerinizi sürümüne eklemek istiyorsanız, normalde bir serialVersionUID 0, ve seri hale getirilmiş verileri değiştiren (geçici olmayan alanlar ekleme veya çıkarma) sınıfınıza yapılan her yapısal değişiklikle çarpın.

Yerleşik de-serileştirme mekanizması (in.defaultReadObject()) verilerin eski sürümlerinden serileştirmeyi reddeder. Ama eğer istersen, kendi kimliğini tanımlayabilirsin readObject ()eski verileri okuyabilen işlev. Bu özel kod daha sonra kontrol edebilir serialVersionUID Verilerin hangi versiyonda olduğunu bilmek ve nasıl serileştirileceğine karar vermek için. Bu sürümleme tekniği, kodunuzun birkaç sürümünden yararlanan seri hale getirilmiş verileri depolarsanız kullanışlıdır.

Ancak, uzun bir zaman dilimi için serileştirilmiş verilerin depolanması çok yaygın değildir. Seri hale getirme mekanizmasının, örneğin bir önbelleğe geçici olarak veri yazmak veya ağ üzerinden kod tabanının ilgili bölümlerinin aynı versiyonuna sahip başka bir programa göndermek için kullanılması çok daha yaygındır.

Bu durumda, geriye dönük uyumluluğu sürdürmekle ilgilenmiyorsunuz. Sadece iletişim kurmakta olan kod tabanlarının, ilgili sınıfların aynı sürümlerine sahip olduğundan emin olmakla ilgileniyorsunuz. Böyle bir kontrolü kolaylaştırmak için, serialVersionUIDDaha önce olduğu gibi ve sınıflarınızda değişiklik yaparken güncellemeyi unutmayın.

Alanı güncellemeyi unutursanız, farklı yapıya sahip ancak farklı bir sınıfın iki farklı sürümü olabilir. serialVersionUID. Bu olursa, varsayılan mekanizma (in.defaultReadObject()) herhangi bir fark saptamayacak ve uyumsuz verileri serileştirmeye çalışacaktır. Artık bir şifreli çalışma zamanı hatası veya sessiz bir hata (boş alanlar) ile sonuçlanabilir. Bu tür hataların bulunması zor olabilir.

Bu nedenle, bu platform size yardımcı olmak için Java platformu size serialVersionUID manuel. Bunun yerine, sınıf yapısının bir karması derleme zamanında oluşturulacak ve kimlik olarak kullanılacaktır. Bu mekanizma, aynı kimliğe sahip farklı sınıf yapılarına sahip olmadığınızdan emin olur ve bu nedenle, yukarıda belirtilen bu izlenmesi zor çalışma zamanı serileştirme hatalarını almazsınız.

Ancak, otomatik oluşturulan kimlik stratejisinin arka tarafı var. Yani, aynı sınıfın oluşturulmuş kimlikleri derleyiciler arasında farklılık gösterebilir (yukarıda Jon Skeet tarafından belirtildiği gibi). Bu nedenle, farklı derleyicilerle derlenen kodlar arasında serileştirilmiş veri iletişim kurarsanız, ids'in el ile tutulması önerilir.

Ayrıca, bahsedilen ilk kullanım örneğinde 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ştiklerini daha fazla kontrol etmek için.


96
2017-10-03 06:05



Geçici olmayan alanlar eklemek veya kaldırmak, sınıf serileştirmesini uyumsuz kılmaz. Bu nedenle, bu değişikliklerde 'vurmak' için bir sebep yoktur. - user207421
@ EJP: Huh? Veri eklemek kesinlikle benim dünyamdaki serileştirme verilerini değiştirir. - Alexander Torstling
@AlexanderTorstling Yazdıklarımı okuyun. Seri hale getirme verisini değiştirmediğini söylemedim. 'Sınıf serileştirme-uyumsuz' yapmaz 'dedim. Aynı şey değil. Nesne Serialization Spesifikasyonunun Versioning bölümünü okumalısınız. - user207421
@EJP: Geçici olmayan bir alan eklemenin, zorunlu olarak sınıf serileştirmesini uyumsuz kıldığı anlamına gelmediğini, ancak seri hale getirilmiş verileri değiştiren yapısal bir değişiklik olduğunun farkına varıyorum. Daha sonra yazımda da açıkladığım geriye dönük uyumluluk. Tam olarak ne anlamı var? - Alexander Torstling
Benim amacım dediğim gibi kalır. Geçici olmayan alanların eklenmesi veya kaldırılması, Sınıflandırmayı uyumsuz kılar. Bu nedenle, her yaptığınızda serialVersionUID değerini vurmanıza gerek yoktur. - user207421


Nedir serialVersionUID ve neden kullanmalıyım?

SerialVersionUID her sınıf için benzersiz bir tanımlayıcıdır JVM Serialization, Serileştirme sırasında yüklenirken 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 denetim sağlar, ancak JVM belirtmezseniz bir tane oluşturur. Oluşturulan değer farklı derleyiciler arasında farklılık gösterebilir. Dahası, bazen sadece eski serileştirilmiş nesnelerin serileştirilmesini yasaklamak için bir sebep istersiniz [backward incompatibility] ve bu durumda sadece serialVersionUID değerini değiştirmeniz gerekir.

javadocs için Serializable söylemek:

varsayılan serialVersionUID hesaplaması, sınıfa oldukça duyarlıdır   derleyici uygulamalarına göre değişebilen ayrıntılar ve   böylece beklenmedik sonuçlanır InvalidClassExceptions sırasında   deserialization.

Bu nedenle, bize daha fazla kontrol verdiğinden serialVersionUID bildirmelisiniz.

Bu makale konuyla ilgili bazı iyi noktaları var.


62
2017-10-17 04:28



@Vinothbabu ancak serialVersionUID statik olduğundan statik değişkenler serileştirilemez. sonra nasıl jvm, deserializing nesnesinin sürümünün ne olduğunu bilmeden sürümü kontrol edecektir - Kranthi Sama
Bu cevapta bahsedilmeyen tek şey, körü körüne dahil olmak üzere istenmeyen sonuçlara neden olabileceğinizdir. serialVersionUID nedenini bilmeden. Tom Anderson'ın MetroidFan2002'nin cevabı hakkındaki yorumu şunları söylüyor: "Kalıcı depolama için serileştirme kullanmıyorsanız, bir değer eklemekten ziyade @SuppressWarnings kullanmanız gerektiğini söyleyebilirim. Sınıfı daha az karmaşık hale getiriyor ve yeteneğini koruyor. uyumsuz değişikliklerden korunmak için serialVersionUID mekanizması. " - Kirby
serialVersionUIDolduğu değil Her sınıf için 'benzersiz bir tanımlayıcı'. Tam nitelikli sınıf adı budur. Bu bir versiyon gösterge. - user207421


Orijinal soru 'neden önemli' ve 'örnek' diye sordu. Serial Version ID yararlı olur. Peki bir tane buldum.

Oluşturduğunuzu varsayalım Car sınıfını örneklendirin ve bir nesne akışına yazın. Düzleştirilmiş araba nesnesi bir süre dosya sisteminde oturur. Bu arada Car sınıf yeni bir alan ekleyerek değiştirilir. Daha sonra, düzleştirilmiş okumayı denediğinizde (yani, deserialize) Car nesne, sen java.io.InvalidClassException - Çü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. Bunu gerçekten düşünürseniz, yeni alanın eklenmesi nedeniyle istisna atılır. Açık bir serialVersionUID bildirerek kendinizin sürümlerini kontrol ederek atılan bu özel durumdan kaçınabilirsiniz. Açıkça bildirmek için küçük bir performans avantajı da vardır. serialVersionUID(çünkü hesaplanması gerekmez). Bu nedenle, aşağıda gösterildiği gibi oluşturduğunuz anda seri hale getirilebilir sınıflarınıza kendi serialVersionUID'nizi eklemeniz en iyi uygulamadır:

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

42
2018-04-07 10:43



Ve her bir UID'ye 1L değil rastgele bir uzun sayı atamalısınız. - abbas
@abbas 'Bunu yapmalı mı?' Lütfen ne gibi bir fark yarattığını açıklayın. - 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ı sayıyı atarsanız, serileştirmek için doğru sınıfı bulamazsınız. Yani, sınıfta bir değişiklik yaptığınızda, sürümü de değiştirmek daha iyidir. - abbas
@abbas, bu niyetin artmakta olan doğal sayıları kullanarak çarpışmaz 1 ve bunun gibi. - Vadzim
@BillK, serialization kontrolünün classname ve serialVersionUID çiftine bağlı olduğunu düşündüm. Dolayısıyla farklı sınıf ve kütüphanelerin farklı numaralandırma şemaları herhangi bir şekilde müdahale edemez. Yoksa kod üreten kütüphaneleri mi ima ettiniz? - Vadzim