Преимущество генерируемого serialVersionID вместо 1L, 2L,

У меня есть дискуссия с коллегой о serialVersionUID сериализуемых классов: он всегда начинается с serialVersionUID = 1L а затем увеличивает его на единицу, когда происходят значительные изменения в классе.

Классы JDK всегда, кажется, используют более сложные, сгенерированные serialVersionUID, как в java.lang.String учебный класс:

private static final long serialVersionUID = -6849794470754667710L;

Теперь мой коллега спрашивает о преимуществах этого вида serialVersionUID по сравнению с гораздо более простым serialVersionUID, таким как 1L, 2L, 3L...?

Мы также искали SOF, но не очень довольны полученными ответами, например, в разделе " Почему генерировать длинный serialVersionUID вместо простого 1L"?,

На мой взгляд, преимущество использования сгенерированных идентификаторов заключается в том, что им не нужна информация о "старых" версиях класса. Но при увеличении идентификаторов вручную вы должны знать максимальное значение. Это может показаться тривиальным (если просто посмотреть на текущий serialVersionUID и увеличить его на 1), но может оказаться более сложным в больших программных проектах, больших группах разработчиков или в распределенных средах.

2 ответа

Преимущество использования сгенерированного в том, что он совместим с предыдущей версией класса, если он вышел без serialVersionUID в дикой природе.

Сказав это, ваш коллега почти наверняка ошибается, увеличивая его. serialVersionUID следует менять только в тот момент, когда вы соглашаетесь с тем, что класс изменился безвозвратно, и вы намеренно хотите ввести несовместимость сериализации. Времена, когда это происходит в природе, встречаются редко, ограничиваясь случаями, когда вы изменяете наследование класса или типы полей-членов несовместимым способом. Если вы решили сделать класс Serializable Вы уже должны были принять режим, в котором это не происходит.

Это интересный вопрос, прямо к сути: я не знаю.

SUID является частью общедоступного API. После того, как вы опубликовали API, который используется вне вашего контроля, например, JDK, вы не сможете изменить это число, не нарушив совместимость.

Так что я не вижу преимущества использования числа типа 32432544354343L вместо 1L.

Но для внутренней разработки я вижу небольшое преимущество, начиная с числа вроде 1L:

Допустим, у нас есть 3 баночки клиент-серверного приложения RMI:

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

В файле api.jar есть несколько бизнес-классов, таких как Song, Album, ... используемых клиентом и сервером, которые сериализуются.

Теперь мы начинаем с SUID 1L для некоторых из этих классов, а после выпуска мы меняем внутренний формат одного из этих классов, поэтому мы увеличиваем SUID до 2L.

Теперь и клиентский, и серверный компоненты должны включать новый файл api.jar. Если мы допустим ошибку и забудем обновить клиент или сервер с новой зависимостью api.jar, то при десериализации будет исключение. Сообщение в исключении будет содержать несовместимые SUID.

Так что здесь число 1L и 2L в сообщении. 2L > 1L, следовательно, мы знаем, что компонент использует старый api.jar. Сгенерированные IDE числа, такие как 123434534553L и 654642646363L, мы не знаем, какой компонент использует старый файл api.jar.

Но с другой стороны, даже новые классы JDK, такие как LocalDate, используют числа типа 123434534553L вместо более простых. В apache commons-lang, кажется, есть смесь, например, FastDateParser.java использует простой 3L.

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

Странный...

Другие вопросы по тегам