2008-09-03 18 views
7

W języku Java statyczne i przejściowe pola nie są serializowane. Jednak dowiedziałem się, że inicjalizacja pól statycznych powoduje, że wygenerowany serialVersionUID zostanie zmieniony. Na przykład static int MYINT = 3; powoduje zmianę identyfikatora serialVersionUID. W tym przykładzie ma to sens, ponieważ różne wersje tej klasy otrzymywałyby różne wartości początkowe. Dlaczego każda inicjalizacja zmienia identyfikator serialVersion? Na przykład static String MYSTRING = System.getProperty("foo"); powoduje również zmianę identyfikatora serialVersionUID.Serializacja Java z inicjalizacją statyczną

Moje pytanie brzmi: dlaczego inicjalizacja za pomocą metody powoduje, że serialVersionUID ulega zmianie. Problemem, który uderzyłem, było dodanie nowego pola statycznego, które zostało zainicjalizowane wartością właściwości systemu (getProperty). Ta zmiana spowodowała wyjątek serializacji na zdalnym wywołaniu.

Odpowiedz

5

Możesz znaleźć informacje na ten temat w bug 4365406 i algorithm for computing serialVersionUID. Zasadniczo, podczas zmiany inicjalizacji twojego static elementu z System.getProperty(), kompilator wprowadza nową klasę static w klasie odwołującej się do klasy System (Zakładam, że klasa System była wcześniej nieodniesiona w klasie), a ponieważ ta właściwość została wprowadzona przez kompilator nie jest prywatny, bierze udział w obliczeniach serialVersionUID.

Moralność: zawsze używać wyraźny serialVersionUID, zaoszczędzisz kilka cykli procesora i jakieś bóle głowy :)

0

Jeśli prawidłowo odczytam specyfikację, automatyczna serialVersionUID nie powinna się zmienić, jeśli zmieni się wartość statycznego pola przejściowego. Spójrz na Chapter 5.6 specyfikacji.

Jednak, jeśli myślisz o tym trochę - zacząć od szeregowania obiektu, który ma static int MYINT = 3, po czym deserializowania klasę można oczekiwać, aby uzyskać ten sam obiekt z powrotem, czyli z MYINT = 3. Tak więc, jeśli zmienisz statyczną inicjalizację, możesz zmienić wartość serialVersionUID, ponieważ nie możesz odzyskać tego samego obiektu.

Anyways, mieć to na wszystkich serializować klas i można kontrolować serialVersionUID:

private static final long serialVersionUID = 7526472295622776147L; 
0

zaktualizowałem pytanie jest bardziej wyraźne. Rozumiem, dlaczego inicjalizacja z literalną zmianą serialVersionUID, ale nie to, dlaczego inicjalizacja dynamiczna go zmienia. Jeśli zainicjujesz za pomocą metody, wartość oczywiście zawsze może być inna.

Jednoznacznie można ustawić serialVersionUID w kolejnej wersji klasy tylko wtedy, gdy masz pewność, że jest to bezpieczna zmiana.

2

Automatyczne serialVersionUID jest obliczana na podstawie członków klasy. Można je wyświetlić dla pliku klasy za pomocą narzędzia javap w Sun JDK.

W przypadku wymienionym w pytaniu członkiem dodawanym/usuwanym jest inicjator statyczny. Pojawia się jako() V w plikach klas. Zawartość metody można zdemontować za pomocą polecenia javap -c. Powinieneś być w stanie rozpoznać wywołanie System.getProperty ("foo") i przypisanie do aplikacji MYSTRING. Jednak przypisanie z literałem łańcuchowym (lub dowolną stałą czasu kompilacji zdefiniowaną w Specyfikacji Języka Java) obsługiwane jest bezpośrednio przez plik klasy, co eliminuje potrzebę statycznego inicjalizatora.

Powszechnym przypadkiem kierowania kodu na J2SE 1.4 (użyj -source 1.4 -get 1.4) lub wcześniejszego są pola statyczne dla starych wystąpień Class, które pojawiają się jako klasy w kodzie źródłowym (MyClass.class). Instancja klasy jest sprawdzana na żądanie przy użyciu Class.forName i przechowywana w polu statycznym. To jest to pole statyczne, które zakłóca serialVersionUID. Od wersji J2SE 5.0, wariant kodu operacyjnego ldc zapewnia bezpośrednią obsługę literałów klasy, eliminując potrzebę stosowania pola syntetycznego. Znowu wszystko to można pokazać za pomocą javap -c.

Powiązane problemy