Преимущество генерируемого 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.
Странный...