Когда класс реализует Serializable в Eclipse, у меня есть два варианта: добавить по умолчанию serialVersionUID(1L)
или сгенерированный serialVersionUID(3567653491060394677L)
. Я думаю, что первый круче, но много раз я видел людей, использующих второй вариант. Есть ли причина для генерации long serialVersionUID
?
210
0L
только изначально.Ответы:
Насколько я могу сказать, это было бы только для совместимости с предыдущими выпусками. Это будет полезно только в том случае, если вы ранее пренебрегали использованием serialVersionUID, а затем внесли изменение, которое, как вы знаете, должно быть совместимым, но которое приводит к прерыванию сериализации.
Посмотрите Спецификацию Сериализации Java для получения дополнительной информации.
источник
Цель UID версии сериализации состоит в том, чтобы отслеживать различные версии класса, чтобы выполнить правильную сериализацию объектов.
Идея состоит в том, чтобы сгенерировать идентификатор, который является уникальным для определенной версии класса, который затем изменяется при добавлении в класс новых сведений, таких как новое поле, которые могут повлиять на структуру сериализованного объекта.
Всегда использование одного и того же идентификатора, например,
1L
означает, что в будущем, если определение класса будет изменено, что приведет к изменениям в структуре сериализованного объекта, будет высокая вероятность возникновения проблем при попытке десериализации объекта.Если идентификатор не указан, Java фактически рассчитает для вас идентификатор на основе полей объекта, но я считаю, что это дорогостоящий процесс, поэтому его предоставление вручную повысит производительность.
Вот несколько ссылок на статьи, которые обсуждают сериализацию и управление версиями классов:
источник
Note - It is strongly recommended that all serializable classes explicitly declare serialVersionUID values, since the default serialVersionUID computation is highly sensitive to class details that may vary depending on compiler implementations, and can thus result in unexpected serialVersionUID conflicts during deserialization, causing deserialization to fail.
Приведенный выше комментарий был взят из спецификации сериализации объектов Java версии 6.0Основная причина для сгенерированного - сделать его совместимым с существующей версией класса, в которой уже есть постоянные копии.
источник
«Длинное» значение по умолчанию
serialVersionUID
- это значение по умолчанию, как определено Спецификацией Сериализации Java , вычисленное из поведения сериализации по умолчанию.Поэтому, если вы добавите номер версии по умолчанию, ваш класс будет (де) сериализоваться быстрее, если ничего не изменилось структурно, но вы должны будете позаботиться о том, чтобы при изменении класса (добавление / удаление полей) вы также обновляли серийный номер.
Если вам не нужно быть совместимым с существующими битовыми потоками, вы можете просто поместить
1L
туда и при необходимости увеличить версию, когда что-то изменится. То есть, когда версия сериализации по умолчанию измененного класса будет отличаться от версии старого класса по умолчанию.источник
Вы обязательно должны создавать serialVersionUID каждый раз, когда определяете реализующий класс
java.io.Serializable
. Если вы этого не сделаете, он будет создан для вас автоматически, но это плохо. Автоматически генерируемый serialVersionUID основан на сигнатурах методов вашего класса, поэтому, если вы в будущем измените свой класс для добавления метода (например), десериализация «старых» версий класса завершится неудачно. Вот что может произойти:источник
Если вы не укажете serialVersionUID, то Java сделает его на лету. Сгенерированный serialVersionUID - это число. Если вы изменяете что-то в своем классе, что на самом деле не делает ваш класс несовместимым с предыдущими сериализованными версиями, но меняет хеш, то вам нужно использовать сгенерированный serialVersionUID с очень большим числом (или «ожидаемое» число из сообщения об ошибке) , В противном случае, если вы все отслеживаете сами, 0, 1, 2 ... лучше.
источник
Когда вы используете serialVersionUID (1L) вместо генерации serialVersionUID (3567653491060394677L), вы что-то говорите.
Вы говорите, что на 100% уверены, что ни одна система, которая когда-либо будет касаться этого класса, не имеет несовместимой сериализованной версии этого класса с номером версии 1.
Если вы можете придумать какой-либо повод для того, чтобы его история сериализованных версий была неизвестна, это может быть трудно сказать с уверенностью. В течение своей жизни успешный класс будет поддерживаться многими людьми, жить во многих проектах и находиться во многих системах.
Вы можете мучиться из-за этого. Или вы можете сыграть в лотерею в надежде проиграть. Если вы генерируете версию, у вас есть небольшой шанс, что что-то пойдет не так. Если вы предполагаете: «Эй, я уверен, никто еще не использовал 1», ваши шансы больше, чем крошечные. Именно потому, что мы все думаем, что 0 и 1 - это круто, у вас больше шансов попасть в них.
-
Когда вы генерируете serialVersionUID (3567653491060394677L), а не используете serialVersionUID (1L), вы что-то говорите.
Вы говорите, что люди могли либо создавать вручную, либо генерировать другие номера версий за всю историю этого класса, и вам все равно, потому что Лонги чертовски большие числа.
В любом случае, если вы точно не знаете историю номеров версий, использованных при сериализации класса во всей вселенной, где он существует или будет существовать, вы рискуете. Если у вас есть время, чтобы убедиться на 100%, что 1 - это AOK, сделайте это. Если это много работы, идти вперед и слепо генерировать число. Вы скорее выиграете в лотерею, чем ошибетесь. Если это так, дайте мне знать, и я куплю вам пиво.
После всего этого разговора об игре в лотерею у меня могло сложиться впечатление, что serialVersionUID генерируется случайным образом. Фактически, пока диапазон чисел равномерно распределен по каждому возможному значению Long, это было бы хорошо. Однако на самом деле это делается так:
http://docs.oracle.com/javase/6/docs/platform/serialization/spec/class.html#4100
Единственное отличие, которое вы получаете, заключается в том, что вам не нужен источник случайных данных Вы используете изменения в самом классе, чтобы изменить результат. Но по принципу «голубиных отверстий» все еще есть вероятность, что он может пойти не так и столкнуться. Это невероятно невероятно. Так что удачи в извлечении пива из меня.
Однако, даже если класс будет когда-либо жить только в одной системе и одной кодовой базе, думая, что увеличение числа вручную дает вам нулевую вероятность столкновений, просто означает, что вы не понимаете людей. :)
источник
Ну, serialVersionUID является исключением из правила, что «статические поля не сериализуются». ObjectOutputStream каждый раз записывает значение serialVersionUID в выходной поток. ObjectInputStream считывает его обратно, и если значение, считанное из потока, не соответствует значению serialVersionUID в текущей версии класса, то оно генерирует исключение InvalidClassException. Более того, если нет serialVersionUID, официально объявленного в сериализуемом классе, компилятор автоматически добавляет его со значением, созданным на основе полей, объявленных в классе.
источник
Потому что во многих случаях идентификатор по умолчанию не является уникальным. поэтому мы создаем идентификатор для создания уникальной концепции.
источник
Чтобы добавить в ответ @David Schmitts, я бы всегда использовал стандартное значение 1L вне соглашения. Я только должен был вернуться и изменить некоторые из них несколько раз, но я знал это, когда вносил изменения и обновлял номер по умолчанию по одному каждый раз.
В моей нынешней компании они требуют автоматически сгенерированного номера, поэтому я использую его для соглашения, но я предпочитаю значение по умолчанию. Я считаю, что если это не соглашение, в котором вы работаете, используйте значение по умолчанию, если только вы не думаете, что по какой-то причине вы будете постоянно изменять структуру сериализованных классов.
источник
Цель UID версии сериализации состоит в том, чтобы отслеживать различные версии класса, чтобы выполнить правильную сериализацию объектов.
Идея состоит в том, чтобы сгенерировать идентификатор, который является уникальным для определенной версии класса, который затем изменяется при добавлении в класс новых сведений, таких как новое поле, которые могут повлиять на структуру сериализованного объекта.
Простое объяснение:
Вы сериализуете данные?
Сериализация - это запись данных класса в файл / поток / и т. Д. Десериализация читает эти данные обратно в класс.
Собираетесь ли вы пойти в производство?
Если вы просто тестируете что-то с неважными / поддельными данными, не беспокойтесь об этом (если только вы не тестируете сериализацию напрямую).
Это первая версия?
Если это так, установите serialVersionUID = 1L.
Это вторая, третья и т. Д. Версия?
Теперь вам нужно побеспокоиться о serialVersionUID, и вам стоит углубиться в это.
По сути, если вы не обновите версию правильно, когда вы обновляете класс, который вам нужен для записи / чтения, вы получите ошибку при попытке прочитать старые данные.
источник