Java сериализация со статической инициализацией - PullRequest
7 голосов
/ 03 сентября 2008

В Java статические и переходные поля не сериализуются. Однако я обнаружил, что инициализация статических полей вызывает изменение сгенерированного serialVersionUID. Например, static int MYINT = 3; вызывает изменение serialVersionUID. В этом примере это имеет смысл, потому что разные версии класса будут иметь разные начальные значения. Почему любая инициализация меняет serialVersionUID? Например, static String MYSTRING = System.getProperty("foo"); также вызывает изменение serialVersionUID.

Если быть точным, мой вопрос заключается в том, почему инициализация с помощью метода приводит к изменению serialVersionUID. Проблема, с которой я столкнулся, заключается в том, что я добавил новое статическое поле, которое было инициализировано значением системного свойства (getProperty). Это изменение вызвало исключение сериализации при удаленном вызове.

Ответы [ 4 ]

5 голосов
/ 04 сентября 2008

Информацию об этом можно найти в ошибке 4365406 и в алгоритме для вычисления serialVersionUID . По сути, при изменении инициализации вашего static члена на System.getProperty() компилятор вводит новое свойство static в вашем классе, ссылающееся на класс System (я предполагаю, что класс System ранее не упоминался в вашем классе ), и поскольку это свойство, введенное компилятором, не является частным, оно участвует в вычислении serialVersionUID.

Мораль : всегда используйте явное serialVersionUID, вы сэкономите некоторые циклы ЦП и некоторые головные боли:)

2 голосов
/ 05 сентября 2008

Автоматический serialVersionUID рассчитывается на основе членов класса. Это можно показать для файла класса с помощью инструмента javap в Sun JDK.

В случае, упомянутом в вопросе, добавляемый / удаляемый элемент является статическим инициализатором. Это отображается как () V в файлах классов. Содержимое метода может быть разобрано с помощью javap -c. Вы должны быть в состоянии разобрать вызов System.getProperty ("foo") и присвоение MYSTRING. Однако присвоение со строковым литералом (или любой константой времени компиляции, как определено в Спецификации языка Java) напрямую поддерживается файлом класса, поэтому устраняется необходимость в статическом инициализаторе.

Распространенным случаем для кода, нацеленного на J2SE 1.4 (используйте -source 1.4 -target 1.4) или более ранние версии, являются статические поля для старых экземпляров Class, которые отображаются как литералы класса в исходном коде (MyClass.class). Экземпляр класса ищется по требованию с помощью Class.forName и хранится в статическом поле. Именно это статическое поле разрушает serialVersionUID. Начиная с J2SE 5.0, вариант кода операции ldc обеспечивает прямую поддержку литералов классов, устраняя необходимость в синтетическом поле. Опять же, все это можно показать с помощью javap -c.

0 голосов
/ 03 сентября 2008

Я обновил вопрос, чтобы быть более понятным. Я понимаю, почему инициализация с помощью литерала меняет serialVersionUID, но не почему динамическая инициализация меняет его. Если вы инициализируете методом, значение, конечно, всегда может быть другим.

Установка serialVersionUID явно подходит для последующей версии класса, только если вы уверены, что это безопасное изменение.

0 голосов
/ 03 сентября 2008

Если я правильно прочитал спецификацию, автоматическое serialVersionUID не должно измениться, если вы измените значение статического переходного поля. Взгляните на главу 5.6 Спецификации.

Однако , если немного подумать об этом - вы начинаете с сериализации объекта, имеющего static int MYINT = 3, когда вы затем десериализируете класс, вы ожидаете получить тот же объект обратно, то есть MYINT = 3. Итак, если вы измените статическую инициализацию, вы ожидаете, что serialVersionUID изменится, потому что вы не можете вернуть тот же объект снова.

В любом случае , сохраните это во всех ваших сериализуемых классах, и вы можете контролировать serialVersionUID:

private static final long serialVersionUID = 7526472295622776147L;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...