Zaćmienie wydaje ostrzeżenia, gdy serialVersionUID
brakuje jakiegoś .
Klasyfikowalna klasa Foo nie deklaruje statycznego końcowego pola serialVersionUID typu long
Co to jest serialVersionUID
i dlaczego jest ważne? Pokaż przykład, w którym brak serialVersionUID
spowoduje problem.
java
serialization
serialversionuid
Ashokgelal
źródło
źródło
Odpowiedzi:
Dokumenty dla
java.io.Serializable
są prawdopodobnie tak dobrym wyjaśnieniem, jak można uzyskać:źródło
Jeśli serializujesz tylko dlatego, że musisz serializować ze względu na implementację (kogo to obchodzi, jeśli serializujesz
HTTPSession
, na przykład ... jeśli jest przechowywany czy nie, prawdopodobnie nie obchodzide-serializing
Cię obiekt formularza), możesz zignoruj to.Jeśli faktycznie używasz serializacji, ma to znaczenie tylko wtedy, gdy planujesz przechowywanie i wyszukiwanie obiektów przy użyciu serializacji bezpośrednio.
serialVersionUID
Reprezentuje wersję klasy i należy zwiększyć, jeśli bieżąca wersja klasy nie jest wstecznie kompatybilny z jego poprzednią wersją.Przez większość czasu prawdopodobnie nie użyjesz serializacji bezpośrednio. W takim przypadku wygeneruj wartość domyślną
SerialVersionUID
, klikając opcję szybkiej poprawki i nie martw się o to.źródło
serialVersionUID
przed niezgodnymi zmianami jest słuszna . Korzystanie z@SuppressWarnings
dokumentów jest lepsze, jeśli nie chcesz używać klasy do trwałego przechowywania.serialVersionUID
jest ostatecznością, radą rozpaczy.Nie mogę przegapić okazji, by podłączyć książkę Josha Blocha „ Effective Java” (wydanie drugie). Rozdział 11 jest niezbędnym źródłem serializacji Javy.
Według Josha automatycznie generowany identyfikator UID jest generowany na podstawie nazwy klasy, zaimplementowanych interfejsów oraz wszystkich członków publicznych i chronionych. Zmiana któregokolwiek z nich w jakikolwiek sposób spowoduje zmianę
serialVersionUID
. Więc nie musisz z nimi zadzierać tylko wtedy, gdy masz pewność, że nie zostanie nigdy serializowanych więcej niż jedna wersja klasy (albo między procesami, albo odzyskana z pamięci w późniejszym czasie).Jeśli zignorujesz je teraz, a później znaleźć, że trzeba zmienić klasę w jakiś sposób, ale zachować zgodność w / starej wersji klasy, można użyć narzędzia JDK serialver do wygenerowania
serialVersionUID
na starej klasy i wyraźnie określone, że w nowej klasie. (W zależności od zmian może być konieczne zaimplementowanie niestandardowej serializacji przez dodaniewriteObject
ireadObject
metody - patrzSerializable
javadoc lub wspomniany rozdział 11).źródło
Możesz powiedzieć Eclipse, aby zignorowało te ostrzeżenia serialVersionUID:
Jeśli nie wiesz, istnieje wiele innych ostrzeżeń, które możesz włączyć w tej sekcji (a nawet niektóre zgłaszać jako błędy), wiele z nich jest bardzo przydatnych:
i wiele więcej.
źródło
serialVersionUID
ułatwia wersjonowanie zserializowanych danych. Jego wartość jest przechowywana z danymi podczas serializacji. Podczas usuwania serializacji sprawdzana jest ta sama wersja, aby zobaczyć, jak dane serializowane są zgodne z bieżącym kodem.Jeśli chcesz zaktualizować swoje dane, zwykle zaczynasz
serialVersionUID
od zera i podbijasz je przy każdej zmianie strukturalnej w swojej klasie, która zmienia zserializowane dane (dodawanie lub usuwanie nieprzechodzących pól).Wbudowany mechanizm deserializacji (
in.defaultReadObject()
) odmówi deserializacji ze starych wersji danych. Ale jeśli chcesz, możesz zdefiniować własną funkcję readObject (), która może odczytywać stare dane. Ten niestandardowy kod może następnie sprawdzićserialVersionUID
, aby dowiedzieć się, w której wersji znajdują się dane, i zdecydować, w jaki sposób należy dokonać serializacji. Ta technika wersjonowania jest przydatna, jeśli przechowujesz serializowane dane, które przetrwają kilka wersji twojego kodu.Ale przechowywanie danych zserializowanych przez tak długi okres nie jest zbyt powszechne. O wiele bardziej powszechne jest stosowanie mechanizmu serializacji do tymczasowego zapisywania danych na przykład w pamięci podręcznej lub wysyłania ich przez sieć do innego programu z tą samą wersją odpowiednich części bazy kodu.
W takim przypadku nie jesteś zainteresowany zachowaniem kompatybilności wstecznej. Zajmujesz się tylko upewnieniem się, że komunikujące się bazy kodu rzeczywiście mają te same wersje odpowiednich klas. Aby ułatwić taką kontrolę, musisz zachować ją
serialVersionUID
tak jak poprzednio i nie zapomnij zaktualizować jej podczas wprowadzania zmian w swoich klasach.Jeśli zapomnisz zaktualizować pole, możesz skończyć z dwiema różnymi wersjami klasy o innej strukturze, ale o tej samej
serialVersionUID
. Jeśli tak się stanie, domyślny mechanizm (in.defaultReadObject()
) nie wykryje żadnej różnicy i spróbuje usunąć serializację niekompatybilnych danych. Teraz możesz skończyć z tajemniczym błędem środowiska wykonawczego lub cichą awarią (pola zerowe). Tego rodzaju błędy mogą być trudne do znalezienia.Aby pomóc w tym przypadku, platforma Java oferuje wybór nie ustawiania
serialVersionUID
ręcznie. Zamiast tego w czasie kompilacji zostanie wygenerowany skrót struktury klasy i użyty jako identyfikator. Ten mechanizm zagwarantuje, że nigdy nie będziesz mieć różnych struktur klas o tym samym identyfikatorze, a więc nie dostaniesz wspomnianych wyżej trudnych do prześledzenia błędów serializacji.Ale istnieje strategia automatycznego generowania identyfikatorów. Mianowicie, że wygenerowane identyfikatory dla tej samej klasy mogą się różnić między kompilatorami (jak wspomniano powyżej Jon Skeet). Jeśli więc komunikujesz dane serializowane między kodem skompilowanym za pomocą różnych kompilatorów, zalecane jest ręczne utrzymanie identyfikatorów.
A jeśli jesteś wstecznie zgodny ze swoimi danymi, tak jak w pierwszym wspomnianym przypadku użycia, prawdopodobnie również chcesz sam zachować identyfikator. Ma to na celu uzyskanie czytelnych identyfikatorów i większą kontrolę nad tym, kiedy i jak się zmieniają.
źródło
SerialVersionUID
jest unikalnym identyfikatorem dla każdej klasy,JVM
używa go do porównywania wersji klasy, upewniając się, że ta sama klasa została użyta podczas serializacji, jest ładowana podczas deserializacji.Określenie jednego daje większą kontrolę, chociaż JVM generuje taki, jeśli nie zostanie określony. Wygenerowana wartość może się różnić w zależności od kompilatora. Co więcej, czasami chcesz po prostu z jakiegoś powodu zabronić deserializacji starych serializowanych obiektów [
backward incompatibility
], w tym przypadku po prostu musisz zmienić serialVersionUID.W Javadocs do
Serializable
powiedzenia :Dlatego musisz zadeklarować serialVersionUID, ponieważ daje nam to większą kontrolę .
Ten artykuł zawiera kilka dobrych punktów na ten temat.
źródło
serialVersionUID
nie wiedząc dlaczego. Komentarz Toma Andersona do odpowiedzi MetroidFan2002 rozwiązuje ten problem: „Powiedziałbym, że jeśli nie używasz serializacji do trwałego przechowywania, powinieneś użyć @SuppressWarnings zamiast dodawać wartość. Mniej zakłóca klasę i zachowuje zdolność mechanizm serialVersionUID, aby chronić Cię przed niezgodnymi zmianami. ”serialVersionUID
to nie za „unikalny identyfikator dla każdej klasy”. Jest to w pełni kwalifikowana nazwa klasy. Jest to wskaźnik wersji .Pierwotne pytanie brzmiało: „dlaczego to ważne” i „przykład”, gdzie
Serial Version ID
byłoby to przydatne. Cóż, znalazłem jeden.Załóżmy, że tworzysz
Car
klasę, tworzysz ją i zapisujesz w strumieniu obiektów. Spłaszczony obiekt samochodowy przez pewien czas znajduje się w systemie plików. Tymczasem jeśliCar
klasa zostanie zmodyfikowana przez dodanie nowego pola. Później, gdy spróbujesz odczytać (tj. Deserializować) spłaszczonyCar
obiekt, otrzymaszjava.io.InvalidClassException
- ponieważ wszystkie klasy możliwe do serializacji otrzymują automatycznie unikalny identyfikator. Ten wyjątek jest zgłaszany, gdy identyfikator klasy nie jest równy identyfikatorowi spłaszczonego obiektu. Jeśli naprawdę się nad tym zastanowisz, wyjątek zostanie zgłoszony z powodu dodania nowego pola. Możesz uniknąć zgłaszania tego wyjątku, samodzielnie kontrolując wersję poprzez zadeklarowanie jawnego serialVersionUID. Istnieje również niewielka korzyść z wydajności w jawnym zadeklarowaniu twojegoserialVersionUID
(ponieważ nie trzeba tego obliczać). Dlatego najlepszą praktyką jest dodawanie własnego serialVersionUID do twoich Serializowalnych klas, jak tylko je utworzysz, jak pokazano poniżej:źródło
1
i tak dalej.Najpierw muszę wyjaśnić, czym jest serializacja.
Serializacja pozwala na konwersję obiektu na strumień, w celu wysłania tego obiektu przez sieć LUB Zapisz do pliku LUB zapisz w DB w celu użycia litery.
Istnieją pewne zasady serializacji .
Obiekt można serializować tylko wtedy, gdy jego klasa lub jego nadklasa implementują interfejs Serializable
Obiekt jest szeregowalny (sam implementuje interfejs Serializable), nawet jeśli jego nadklasa nie jest. Jednak pierwsza nadklasa w hierarchii klasy szeregowalnej, która nie implementuje interfejsu szeregowalnego, MUSI mieć konstruktor bez argumentu. Jeśli zostanie to naruszone, readObject () wygeneruje wyjątek java.io.InvalidClassException w środowisku wykonawczym
Wszystkie typy pierwotne są serializowane.
Pola przejściowe (z modyfikatorem przejściowym) NIE są serializowane (tzn. Nie są zapisywane ani przywracane). Klasa, która implementuje Serializable, musi oznaczyć przejściowe pola klas, które nie obsługują serializacji (np. Strumień plików).
Pola statyczne (z modyfikatorem statycznym) nie są serializowane.
Gdy
Object
jest serializowany, Java Runtime kojarzy numer wersji seryjnej aka, czyliserialVersionID
.Gdzie potrzebujemy serialVersionID: Podczas deserializacji, aby sprawdzić, czy nadawca i odbiorca są kompatybilni w odniesieniu do serializacji. Jeśli odbiornik załaduje klasę w inny sposób,
serialVersionID
deserializacja zakończy sięInvalidClassCastException
.Klasamożliwa doserializacji może
serialVersionUID
jawniezadeklarować swoją własną, deklarując nazwane pole,serialVersionUID
które musi być statyczne, końcowe i długiego typu.Spróbujmy tego na przykładzie.
Utwórz obiekt serializacji
Deserializuj obiekt
UWAGA: Zmień teraz serialVersionUID klasy Employee i zapisz:
I uruchom klasę Reader. Nie uruchamiać klasy Writer, a otrzymasz wyjątek.
źródło
Jeśli nigdy nie będziesz musiał szeregować obiektów w celu bajtowania tablicy i wysyłania / przechowywania ich, nie musisz się tym martwić. Jeśli to zrobisz, musisz wziąć pod uwagę swój serialVersionUID, ponieważ deserializator obiektu dopasuje go do wersji obiektu, którą ma moduł ładujący klasy. Przeczytaj więcej na ten temat w specyfikacji języka Java.
źródło
Jeśli zobaczysz to ostrzeżenie w klasie, nigdy nie zastanawiasz się nad serializacją, a sam nie zadeklarowałeś
implements Serializable
tego, często dzieje się tak , ponieważ odziedziczyłeś po nadklasie, która implementuje Serializable. Często wtedy lepiej byłoby przekazać taki obiekt zamiast korzystać z dziedziczenia.Więc zamiast
zrobić
oraz w odpowiednich metodach wywołaj
myList.foo()
zamiastthis.foo()
(lubsuper.foo()
). (To nie pasuje do wszystkich przypadków, ale wciąż dość często.)Często widzę osoby rozszerzające JFrame lub coś takiego, kiedy tak naprawdę muszą tylko to delegować. (Pomaga to również w automatycznym uzupełnianiu w środowisku IDE, ponieważ JFrame ma setki metod, których nie potrzebujesz, gdy chcesz wywoływać swoje niestandardowe w klasie).
Jednym z przypadków, w których ostrzeżenie (lub serialVersionUID) jest nieuniknione, jest to, że po wyjściu z AbstractAction, zwykle w klasie anonimowej, dodaje się tylko metodę actionPerformed-method. Myślę, że w tym przypadku nie powinno być ostrzeżenia (ponieważ normalnie nie można w sposób wiarygodny serializować i deserializować takich anonimowych klas w różnych wersjach klasy), ale nie jestem pewien, w jaki sposób kompilator mógłby to rozpoznać.
źródło
__AUTOLOAD
, o której nie wiem.Aby zrozumieć znaczenie pola serialVersionUID, należy zrozumieć, jak działa serializacja / deserializacja.
Gdy szeregowany obiekt klasy jest serializowany Java Runtime kojarzy numer seryjny (zwany jako serialVersionUID) z tym serializowanym obiektem. W chwili deserializacji tego serializowanego obiektu Java Runtime dopasowuje serialVersionUID serializowanego obiektu do serialVersionUID klasy. Jeśli oba są równe, to tylko dalszy proces deserializacji spowoduje zgłoszenie wyjątku InvalidClassException.
Stwierdzamy zatem, że aby proces serializacji / deserializacji zakończył się sukcesem, serialVersionUID obiektu serializowanego musi być równoważny serialVersionUID klasy. W przypadku, gdy programista wyraźnie określi wartość serialVersionUID w programie, wówczas ta sama wartość zostanie skojarzona z serializowanym obiektem i klasą, niezależnie od platformy serializacji i deserializacji (np. Serializacja może być wykonana na platformie takiej jak Windows za pomocą sun lub MS JVM i deserializacja mogą znajdować się na innej platformie Linux przy użyciu Zing JVM).
Jednak w przypadku, gdy programista nie określi serialVersionUID, wówczas podczas wykonywania Serialization \ DeSerialization dowolnego obiektu środowisko wykonawcze Java wykorzystuje własny algorytm do jego obliczenia. Ten algorytm obliczeniowy serialVersionUID różni się w zależności od środowiska JRE. Możliwe jest również, że środowisko, w którym obiekt jest szeregowany, używa jednego środowiska JRE (np. SUN JVM), a środowisko, w którym odbywa się deserializacja, używa środowiska Linux Jvm (zing). W takich przypadkach serialVersionUID skojarzony z serializowanym obiektem będzie inny niż serialVersionUID klasy obliczonej w środowisku deserializacji. Z kolei deserializacja nie powiedzie się. Aby uniknąć takich sytuacji / problemów, programista musi zawsze określać serialVersionUID klasy Serializable.
źródło
Nie przejmuj się, domyślna kalkulacja jest naprawdę dobra i wystarcza na 99,9999% przypadków. A jeśli napotkasz problemy, możesz - jak już wspomniano - wprowadzić identyfikatory UID, gdy zajdzie taka potrzeba (co jest bardzo mało prawdopodobne)
źródło
Na przykład, gdy brakujący serialVersionUID może powodować problem:
Pracuję nad aplikacją Java EE, która składa się z modułu WWW korzystającego z
EJB
modułu. Moduł WWW wywołujeEJB
moduł zdalnie i przekazuje argument,POJO
który implementujeSerializable
jako argument.Ta
POJO's
klasa została zapakowana w słoik EJB i wewnątrz własnego słoika w WEB-INF / lib modułu WWW. W rzeczywistości są tej samej klasy, ale kiedy pakuję moduł EJB, rozpakowuję słoik tego POJO, aby spakować go razem z modułem EJB.Wezwanie do
EJB
nie powiodło się z poniższym wyjątkiem, ponieważ nie zadeklarowałem jegoserialVersionUID
:źródło
Zwykle używam
serialVersionUID
w jednym kontekście: gdy wiem, że opuszcza kontekst maszyny wirtualnej Java.Wiedziałbym o tym, kiedy będę używać
ObjectInputStream
iObjectOutputStream
dla mojej aplikacji lub jeśli wiem, że biblioteka / środowisko, którego używam, będzie z niego korzystać. SerialVersionID zapewnia, że różne maszyny wirtualne Java o różnych wersjach lub dostawcy będą współpracować poprawnie lub jeśli będą przechowywane i pobierane poza maszyną wirtualną na przykładHttpSession
dane sesji mogą pozostać nawet podczas ponownego uruchomienia i aktualizacji serwera aplikacji.We wszystkich innych przypadkach używam
ponieważ przez większość czasu ustawienie domyślne
serialVersionUID
jest wystarczające. Obejmuje toException
,HttpServlet
.źródło
Dane pola reprezentują niektóre informacje przechowywane w klasie. Klasa implementuje
Serializable
interfejs, więc zaćmienie automatycznie proponuje deklaracjęserialVersionUID
pola. Zacznijmy od ustawionej tam wartości 1.Jeśli nie chcesz, aby pojawiło się to ostrzeżenie, użyj tego:
źródło
Byłoby miło, gdyby CheckStyle mógł zweryfikować, czy serialVersionUID w klasie, która implementuje Serializable, ma dobrą wartość, tj. Czy pasuje do tego, co wygenerowałby generator id wersji seryjnej. Jeśli masz projekt z wieloma serializowalnymi DTO, na przykład pamiętaj, aby usunąć istniejący serialVersionUID i zregenerować go, jest to ból, a obecnie jedynym sposobem (o którym wiem), aby to zweryfikować, jest regeneracja dla każdej klasy i porównanie z ten stary. To bardzo, bardzo bolesne.
źródło
serialver
, co by wyprodukowało. -1serialVersionUID
1. Jeśli nowsza wersja klasy jest niezgodna, ale nadal wymaga obsługi starych danych, zwiększasz numer wersji i dodajesz specjalny kod do radzić sobie ze starszymi formatami. Płaczę za każdym razem, gdy widzęserialVersionUID
więcej niż 1 cyfrę, albo dlatego, że była to liczba losowa (bezużyteczna), albo dlatego, że klasa najwyraźniej musi poradzić sobie z ponad 10 różnymi wersjami.SerialVersionUID służy do kontroli wersji obiektu. możesz również podać serialVersionUID w pliku klasy. Konsekwencją braku określenia serialVersionUID jest to, że po dodaniu lub zmodyfikowaniu dowolnego pola w klasie już zserializowana klasa nie będzie w stanie odzyskać, ponieważ serialVersionUID wygenerowany dla nowej klasy i dla starego serializowanego obiektu będzie inny. Proces serializacji Java opiera się na poprawnym identyfikatorze serialVersionUID w celu odzyskania stanu obiektu serializowanego i zgłasza wyjątek java.io.InvalidClassException w przypadku niezgodności serialVersionUID
Czytaj więcej: http://javarevisited.blogspot.com/2011/04/top-10-java-serialization-interview.html#ixzz3VQxnpOPZ
źródło
Po co używać klasy
SerialVersionUID
wewnętrznejSerializable
w Javie?Podczas
serialization
działania środowiska wykonawczego Java tworzony jest numer wersji dla klasy, aby można go później przekształcić do postaci szeregowej. Ten numer wersji jest znany jakoSerialVersionUID
Java.SerialVersionUID
służy do wersji danych zserializowanych. Możesz usunąć serializację klasy tylko wtedy, gdy jestSerialVersionUID
zgodna z serializowaną instancją. Gdy nie deklarujemySerialVersionUID
w naszej klasie, środowisko wykonawcze Java generuje je dla nas, ale nie jest to zalecane. Zaleca się deklarowanieSerialVersionUID
jakoprivate static final long
zmiennej, aby uniknąć domyślnego mechanizmu.Gdy deklarujesz klasę jako
Serializable
implementując interfejs znacznikajava.io.Serializable
, środowisko wykonawcze Java zachowuje instancję tej klasy na dysku za pomocą domyślnego mechanizmu serializacji, pod warunkiem, że nie dostosowałeś procesu za pomocąExternalizable
interfejsu.zobacz także Dlaczego warto korzystać z SerialVersionUID w klasie Serializable w Javie
Kod: javassist.SerialVersionUID
źródło
Jeśli chcesz zmienić ogromną liczbę klas, dla których nie ustawiono serialVersionUID, jednocześnie zachowując kompatybilność ze starymi klasami, narzędzia takie jak IntelliJ Idea, Eclipse są niewystarczające, ponieważ generują losowe liczby i nie działają na zbiorze plików za jednym razem. Pojawiam się następujący skrypt bash (przepraszam dla użytkowników systemu Windows, rozważ zakup Maca lub konwersję do Linuksa), aby łatwo zmienić problem serialVersionUID:
zapisz ten skrypt, powiedz do ciebie add_serialVersionUID.sh ~ / bin. Następnie uruchom go w katalogu głównym projektu Maven lub Gradle, np .:
Ten plik .lst zawiera listę plików Java, aby dodać serialVersionUID w następującym formacie:
Ten skrypt używa narzędzia JDK serialVer pod maską. Upewnij się więc, że Twój $ JAVA_HOME / bin znajduje się w ŚCIEŻCE.
źródło
To pytanie jest bardzo dobrze udokumentowane w Effective Java autorstwa Joshua Bloch. Bardzo dobra książka i trzeba ją przeczytać. Przedstawię niektóre z poniższych przyczyn:
Środowisko wykonawcze serializacji zawiera liczbę o nazwie Wersja szeregowa dla każdej klasy możliwej do serializacji. Ten numer nazywa się serialVersionUID. Teraz za tą liczbą kryje się trochę matematyki, która wychodzi na podstawie pól / metod zdefiniowanych w klasie. Dla tej samej klasy za każdym razem generowana jest ta sama wersja. Liczba ta jest używana podczas deserializacji w celu sprawdzenia, czy nadawca i odbiorca obiektu serializowanego załadowali klasy dla tego obiektu, które są kompatybilne w odniesieniu do serializacji. Jeśli odbiorca załadował klasę dla obiektu, który ma inny identyfikator serialVersionUID niż klasy odpowiedniego nadawcy, deserializacja spowoduje wyjątek InvalidClassException.
Jeśli klasa jest serializowalna, możesz również jawnie zadeklarować własny serialVersionUID, deklarując pole o nazwie „serialVersionUID”, które musi być statyczne, końcowe i mieć długi typ. Większość IDE, takich jak Eclipse, pomaga wygenerować ten długi ciąg.
źródło
Za każdym razem, gdy obiekt jest szeregowany, obiekt jest stemplowany numerem identyfikacyjnym wersji dla klasy obiektu. Ten identyfikator nazywa się serialVersionUID i jest obliczany na podstawie informacji o strukturze klasy. Załóżmy, że utworzyłeś klasę Employee i ma ona wersję nr 333 (przypisaną przez JVM). Teraz, kiedy serializujesz obiekt tej klasy (Załóżmy, że obiekt pracownika), JVM przypisze mu identyfikator UID jako # 333.
Rozważ sytuację - w przyszłości musisz edytować lub zmienić klasę, a w takim przypadku, gdy ją zmodyfikujesz, JVM przypisze jej nowy UID (Załóżmy, że # 444). Teraz, gdy spróbujesz deserializować obiekt pracownika, JVM porówna identyfikator wersji obiektu szeregowego (obiekt pracownika) (# 333) z identyfikatorem klasy, tj. # 444 (ponieważ został zmieniony). Dla porównania JVM wykryje, że obie wersje UID są różne, a zatem deserializacja zakończy się niepowodzeniem. Dlatego jeśli serialVersionID dla każdej klasy jest zdefiniowany przez samego programistę. Będzie tak samo, nawet jeśli klasa będzie ewoluować w przyszłości, a zatem JVM zawsze stwierdzi, że klasa jest kompatybilna z serializowanym obiektem, nawet jeśli klasa zostanie zmieniona. Więcej informacji można znaleźć w rozdziale 14 HEAD FIRST JAVA.
źródło
serialVersionUID
przesyłany jest. Nie jest wysyłany z każdym obiektem.Proste wyjaśnienie:
Czy serializujesz dane?
Serializacja polega zasadniczo na zapisywaniu danych klasy do pliku / strumienia / etc. Dezserializacja polega na odczytywaniu tych danych z powrotem do klasy.
Czy zamierzasz wejść do produkcji?
Jeśli tylko testujesz coś z nieistotnymi / fałszywymi danymi, nie przejmuj się tym (chyba że bezpośrednio testujesz serializację).
Czy to jest pierwsza wersja?
Jeśli tak, ustaw
serialVersionUID=1L
.Czy to druga, trzecia itd. Wersja produktu?
Teraz musisz się martwić
serialVersionUID
i zagłębić się w to.Zasadniczo, jeśli nie zaktualizujesz wersji poprawnie podczas aktualizacji klasy, musisz zapisać / odczytać, pojawi się błąd przy próbie odczytania starych danych.
źródło
„serialVersionUID” to 64-bitowa liczba używana do jednoznacznej identyfikacji klasy podczas procesu deserializacji. Podczas serializacji obiektu serialVersionUID klasy również jest zapisywany w pliku. Ilekroć deserializujesz ten obiekt, java w czasie wykonywania wyodrębnia tę wartość serialVersionUID z danych serializowanych i porównuje tę samą wartość skojarzoną z klasą. Jeśli oba się nie zgadzają, zostanie wygenerowany wyjątek „java.io.InvalidClassException”.
Jeśli klasa możliwa do serializacji nie zadeklaruje jawnie serialVersionUID, środowisko wykonawcze serializacji obliczy wartość serialVersionUID dla tej klasy w oparciu o różne aspekty klasy, takie jak pola, metody itp. ,, Możesz skorzystać z tego łącza do aplikacji demonstracyjnej.
źródło
Krótko mówiąc, to pole służy do sprawdzania, czy dane zserializowane mogą być poprawnie przekształcone z postaci szeregowej. Serializacja i deserializacja są często wykonywane przez różne kopie programu - na przykład serwer konwertuje obiekt na ciąg, a klient konwertuje otrzymany ciąg na obiekt. To pole mówi, że oba działają z takim samym wyobrażeniem o tym, czym jest ten obiekt. To pole pomaga, gdy:
masz wiele różnych kopii swojego programu w różnych miejscach (np. 1 serwer i 100 klientów). Jeśli zmienisz obiekt, zmienisz numer wersji i zapomnisz zaktualizować jednego z tych klientów, będzie wiedział, że nie jest on w stanie dokonać deserializacji
zapisałeś swoje dane w jakimś pliku, a później próbujesz go otworzyć za pomocą zaktualizowanej wersji programu ze zmodyfikowanym obiektem - będziesz wiedział, że ten plik nie jest kompatybilny, jeśli utrzymasz odpowiednią wersję
Kiedy to jest ważne
Najbardziej oczywiste - jeśli dodasz niektóre pola do swojego obiektu, starsze wersje nie będą mogły ich używać, ponieważ nie mają tych pól w strukturze obiektu.
Mniej oczywiste - po deserializacji obiektu pola, które nie są obecne w ciągu, będą zachowane jako NULL. Jeśli usunąłeś pole ze swojego obiektu, starsze wersje zachowają to pole jako zawsze NULL, co może prowadzić do złego zachowania, jeśli starsze wersje polegają na danych w tym polu (w każdym razie stworzyłeś je dla czegoś, nie tylko dla zabawy :-))
Najmniej oczywiste - czasami zmieniasz pomysł, który nadałeś sensowi jakiegoś pola. Na przykład, kiedy masz 12 lat, pod „rowerem” masz na myśli „rower”, ale kiedy masz 18 lat, masz na myśli „motocykl” - jeśli Twoi znajomi zaprosą Cię na „przejażdżkę rowerem po mieście” i będziesz jedynym, który przyszedł na rower, nie zrozumiesz, jak ważne jest zachowanie tego samego znaczenia na różnych polach :-)
źródło
Po pierwsze, aby odpowiedzieć na twoje pytanie, kiedy nie deklarujemy SerialVersionUID w naszej klasie, środowisko wykonawcze Java generuje je dla nas, ale ten proces jest wrażliwy na wiele metadanych klasy, w tym liczbę pól, rodzaj pól, modyfikator dostępu do pól, zaimplementowany interfejs według klas itp. Dlatego zaleca się, aby zadeklarować to sami, a Eclipse ostrzega o tym samym.
Serializacja: Często pracujemy z ważnymi obiektami, których stan (dane w zmiennych obiektu) jest tak ważny, że nie możemy ryzykować jego utraty z powodu awarii zasilania / systemu (lub) awarii sieci w przypadku wysłania stanu obiektu do innego maszyna. Rozwiązanie tego problemu nosi nazwę „Trwałość”, co oznacza po prostu utrwalanie (przechowywanie / zapisywanie) danych. Serializacja jest jednym z wielu innych sposobów osiągnięcia trwałości (poprzez zapisanie danych na dysku / pamięci). Podczas zapisywania stanu obiektu ważne jest, aby utworzyć tożsamość obiektu, aby móc go poprawnie odczytać (deserializacja). Ta unikalna identyfikacja to ID to SerialVersionUID.
źródło
Co to jest SerialVersionUID? Odpowiedź: - Powiedzmy, że są dwie osoby, jedna z centrali, a druga z ODC, obie będą odpowiednio wykonywać serializację i deserializację. W tym przypadku w celu uwierzytelnienia, że odbiorca będący w ODC jest osobą uwierzytelnioną, JVM tworzy unikalny identyfikator, który jest znany jako SerialVersionUID.
Oto dobre wyjaśnienie na podstawie scenariusza,
Dlaczego SerialVersionUID?
Serializacja : w momencie serializacji JVM zapisuje unikalny identyfikator dla każdej strony wysyłającej obiekt. JVM jest odpowiedzialny za wygenerowanie tego unikalnego identyfikatora na podstawie odpowiedniego pliku .class, który jest obecny w systemie nadawcy.
Deserializacja : w czasie deserializacji JVM po stronie odbiorcy porówna unikalny identyfikator powiązany z obiektem z unikalnym identyfikatorem klasy lokalnej, tj. JVM utworzy również unikalny identyfikator na podstawie odpowiedniego pliku .class, który jest obecny w systemie odbiorczym. Jeśli oba unikalne identyfikatory są dopasowane, zostanie przeprowadzona tylko deserializacja. W przeciwnym razie otrzymamy wyjątek Runtime Exception z informacją InvalidClassException. Ten unikalny identyfikator jest niczym innym jak SerialVersionUID
źródło