2016-11-15 8 views
6

Mam dyskusję z kolegą na temat serialVersionUID klas serializowalnych: Zawsze zaczyna się od serialVersionUID = 1L, a następnie zwiększa ją o jeden, gdy są pewne istotne zmiany w klasie.Korzyści z wygenerowanego identyfikatora serialVersionID zamiast 1L, 2L,

Klasy JDK zawsze wydają się używać bardziej skomplikowane, generowane serialVersionUIDs jak w klasie java.lang.String:

private static final long serialVersionUID = -6849794470754667710L; 

Teraz mój kolega pyta o korzyści z tego rodzaju serialVersionUID kontra znacznie prostszych serialVersionUID jak 1L, 2L , 3L ...?

Szukaliśmy również SOF, ale nie jesteśmy zbyt zadowoleni z podanych odpowiedzi, na przykład w Why generate long serialVersionUID instead of a simple 1L?.

Moim zdaniem zaletą korzystania z generowanych identyfikatorów jest to, że nie potrzebuje żadnych informacji o "starszych" wersjach klas. Jednak przy ręcznym zwiększaniu liczby identyfikatorów, musisz znać jak dotąd najwyższą wartość. Może to zabrzmieć banalnie (patrząc na bieżący serialVersionUID i zwiększyć go o 1), ale może być bardziej skomplikowany w większych projektach programistycznych, większych zespołach programistycznych lub w środowiskach rozproszonych.

+2

Jeśli zwiększysz go, gdy wystąpią znaczące zmiany w klasie, oznacza to, że akceptujesz, że te zmiany powodują, że nowa wersja klasy jest niezgodna ze starszymi wersjami. W takim przypadku brak w ogóle identyfikatora serialVersion jest najmniej rozwlekłym i najprostszym rozwiązaniem. –

+4

SerialVersionUID najlepiej jest traktować jako śledzącą * zgodną wersję serializowanej wersji * niż wersję klasy. Klasy mogą być modyfikowane w szerokim zakresie bez żadnych zmian w sposobie zapisywania stanu i odczytu z postaci zserializowanej. Dopóki klasa pozostaje zgodna ze swoją serializowaną formą, nie ma powodu, aby zmieniać serialVersionUID (dlatego najlepszą praktyką jest jawne określenie). – scottb

+0

Faceci nie zrozumcie mnie źle, wiem, jak działa mechanizm serializacji i nie mam z tym problemu. Zastanawiam się tylko nad zaletą lub wadą generowanych seryjnych ID użytkowników w porównaniu z nowymi. –

Odpowiedz

-1

To interesujące pytanie, od razu do rzeczy: nie wiem.

SUID jest częścią publicznego interfejsu API. Po opublikowaniu interfejsu API, który jest używany poza standardem , sterowanie, takie jak JDK, nie może zmienić tego numeru bez utraty zgodności.

Więc nie widzę żadnej korzyści z używania numeru jak 32432544354343L zamiast 1L.

Ale dla rozwoju wewnątrzobiektowych widzę małą zaletą począwszy od numeru jak 1L:

powiedzmy, że mamy 3 słoiki z aplikacji klient-serwer RMI:

  • client.jar
  • server.jar
  • api.jar

W api.jar re to niektóre klasy biznesowe, takie jak Piosenka, Album, ... używane przez klienta i serwer, z których można serializować .

Teraz zaczynamy od SUID 1L dla niektórych z tych klas , a po wydaniu zmieniamy wewnętrzny format jednego tych klas, więc zwiększamy SUID do 2L.

Teraz zarówno klient, jak i składniki serwera muszą zawierać nowy api.jar. Jeśli popełnimy błąd i zapomnimy zaktualizować klienta lub serwer z nową zależnością api.jar, podczas deserializacji wystąpi wyjątek . Komunikat w wyjątku będzie obejmował niezgodne identyfikatory SUID.

Tak tutaj liczba 1L i 2L są w wiadomości. 2L> 1L, stąd wiemy, że komponent używa starego api.jar. Z liczbami generowanymi przez IDE, takimi jak 123434534553L i 654642646363L, nie mamy wiedzieć, który składnik używa starego api.jar.

Ale z drugiej strony nawet nowe klasy JDK, takie jak LocalDate, używają liczb takich jak 123434534553L zamiast prostszego. W apache commons-lang wydaje się, że istnieje mieszanka, np. , np. FastDateParser.java używa prostego 3L.

https://github.com/apache/commons-lang/blob/master/src/main/java/org/apache/commons/lang3/time/FastDateParser.java

Dziwne ...

+0

W takim przypadku wystąpi wyjątek w przypadku deserializacji, jeśli zmiana jest niezgodna. Zmiana 'serialVersionUID' tylko w celu celowego spowodowania tego wyjątku, włączając przypadki, w których może nie być to konieczne, nie ma większego sensu. – EJP

1

Zaletą korzystania wygenerowany jeden jest to, że jest kompatybilny z poprzednią wersją klasy jeśli uciekł bez serialVersionUID na wolność.

Powiedziawszy to, twój kolega prawie na pewno nie jest w stanie go zwiększyć. Zmienną serialVersionUID należy zmienić tylko w punkcie, w którym akceptujesz, że klasa się nieodwracalnie zmieniła i celowo chcesz wprowadzić niekompatybilność z serializacją. Czasy, w których ma to miejsce w przyrodzie, są rzadkością, ograniczając się do przypadków, w których zmieniasz dziedziczenie klasy lub typy pól członków w sposób niekompatybilny. Jeśli zdecydowałeś się utworzyć klasę Serializable, powinieneś już zaakceptować reżim , w którym to nie nastąpi.

+0

Aby poradzić sobie z wersjonowaniem (i np. Dodawaniem nowych pól do klasy), należy rozważyć zastosowanie z własnym polem wersji. Jak pokazano tutaj: http://stackoverflow.com/questions/3678136/managing-several-versions-of-serialized-java-objects#answer-14946099 – szymond

+0

@śmieond lub dziedziczenie. – EJP

Powiązane problemy