serialVersionUID
облегчает управление версиями сериализованных данных. Его значение сохраняется вместе с данными при сериализации. При десериализации, эта же версия проверяется, чтобы увидеть, как сериализованные данные соответствуют текущему коду.
Если вы хотите создать версию ваших данных, вы обычно начинаете с serialVersionUID
0 и увеличиваете его при каждом структурном изменении вашего класса, которое изменяет сериализованные данные (добавляя или удаляя непереходные поля).
Встроенный механизм десериализации ( in.defaultReadObject()
) откажется от десериализации старых версий данных. Но если вы хотите, вы можете определить свою собственную функцию readObject (), которая может считывать старые данные. Этот пользовательский код может затем проверить serialVersionUID
, чтобы узнать, в какой версии находятся данные, и решить, как десериализовать их. Этот метод управления версиями полезен, если вы храните сериализованные данные, которые сохраняются в нескольких версиях вашего кода.
Но хранение сериализованных данных в течение такого длительного промежутка времени не очень распространено. Гораздо более распространенным является использование механизма сериализации для временной записи данных, например, в кэш или отправки их по сети в другую программу с той же версией соответствующих частей кодовой базы.
В этом случае вы не заинтересованы в поддержании обратной совместимости. Вы заинтересованы только в том, чтобы убедиться, что базы кода, которые общаются, действительно имеют одинаковые версии соответствующих классов. Чтобы упростить такую проверку, вы должны поддерживать то же, serialVersionUID
что и раньше, и не забывать обновлять ее при внесении изменений в ваши классы.
Если вы забудете обновить поле, вы можете получить две разные версии класса с разной структурой, но с одинаковой serialVersionUID
. Если это произойдет, механизм по умолчанию ( in.defaultReadObject()
) не обнаружит различий и попытается десериализовать несовместимые данные. Теперь вы можете получить загадочную ошибку во время выполнения или тихий сбой (пустые поля). Эти типы ошибок могут быть трудно найти.
Таким образом, чтобы помочь этому варианту использования, платформа Java предлагает вам выбор не устанавливать serialVersionUID
вручную. Вместо этого, хэш структуры класса будет сгенерирован во время компиляции и использован как идентификатор. Этот механизм гарантирует, что у вас никогда не будет разных структур классов с одинаковым идентификатором, и поэтому вы не получите этих трудно отслеживаемых ошибок сериализации во время выполнения, упомянутых выше.
Но есть и обратная сторона автоматически генерируемой стратегии id. А именно, что сгенерированные идентификаторы для одного и того же класса могут отличаться в разных компиляторах (как упомянуто Джоном Скитом выше). Поэтому, если вы передаете сериализованные данные между кодом, скомпилированным с разными компиляторами, рекомендуется в любом случае поддерживать идентификаторы вручную.
И если вы обратно совместимы с вашими данными, как в первом упомянутом случае использования, вы также, вероятно, захотите сохранить идентификатор самостоятельно. Это для того, чтобы получить читаемые идентификаторы и иметь больший контроль над тем, когда и как они меняются.