Явный serialVersionUID считается вредным?
Я, вероятно, рискую понизить это.
Мне кажется, что явно указывать serialVersionUID для новых классов плохо. Рассмотрим два случая не изменять его, когда макет должен был быть изменен, и изменять его, когда он не должен был это делать.
Не изменяется, когда это должно было быть изменено, происходит почти только тогда, когда это явно. В этом случае это приводит к некоторым очень тонким, трудно обнаруживаемым ошибкам. Особенно во время разработки, когда макет класса часто меняется. Но если он не был явно указан, он изменится, и десериализация будет громко прервана, что, скорее всего, будет решено путем очистки хранилища.
Изменение его, когда не должно быть, произойдет почти только тогда, когда оно неявно. Это редкий случай, когда макет класса изменился, но мы все еще хотим десериализовать из старых сериализованных BLOB-объектов. Это, вероятно, будет обнаружено во время QA (странные ошибки после обновления с 5.2 до 5.2.1, см. Трассировку прикрепленного стека) и может быть тривиально исправлено путем установки явного значения.
Комментарии?
6 ответов
Изменение, когда оно не должно происходить, может происходить по причинам, отличным от изменений макета класса - проблема в том, что это зависит от реализации компилятора. Если вы выполняете отладку в Eclipse, но производите сборку с помощью javac, вы можете получить два несовместимых набора данных.
На моей работе мы явно запрещаем указывать serialVersionUID, именно из-за проблем, которые вы поднимаете.
Кроме того, классы, которые мы сохраняем, используются только для хранения данных без какой-либо логики, поэтому они изменяются только из-за изменения элементов данных.
Чтобы еще больше подчеркнуть сказанное Джоном Скитом и опровергнуть комментарий:
"Если вам это не нужно (то есть вы всегда сериализуете и десериализуете одну и ту же версию класса), то вы можете спокойно пропустить явное объявление"
Даже если вы не выполняете сериализацию в течение длительного времени и используете одну и ту же версию класса, у вас все равно могут возникнуть проблемы. если вы пишете клиент-серверный код и клиентский код может работать с версией / реализацией jvm, отличной от серверной, у вас могут возникнуть те же проблемы с несовместимыми serialversionuids.
Подводя итог, можно сказать, что единственное время, когда "безопасно" не указывать serialversionuids, - это когда вы не сериализуете в долгосрочной перспективе и вам гарантировано, что все потребители сериализованных данных будут использовать ту же реализацию и версию jvm, что и исходный производитель.
короче говоря, не использование serialversionuid, как правило, более опасная ситуация.
Когда вам нужно поддерживать долговременное постоянство с помощью сериализации, вам почти всегда нужно использовать собственный код для поддержки этого и нужно явно установить serialVersionUID
иначе старая сериализованная версия не будет десериализуема новым кодом.
Эти сценарии уже требуют большой осторожности, чтобы все случаи были правильными, когда класс меняется, поэтому serialVersionUID - это наименьшая из ваших проблем.
Если вам это не нужно (т. Е. Вы всегда сериализуете и десериализуете одну и ту же версию класса), то вы можете спокойно пропустить явное объявление, поскольку вычисленное значение обеспечит использование правильной версии.
Если вы просто используете сериализацию для удаленного вызова метода, например, для вызова EJB, где классы клиента и сервера и jvm одинаковы, что, как я подозреваю, является наиболее распространенным вариантом использования, тогда явно задайте serialVersionUID (как, например, eclipse предполагает) может причинить вам значительную боль в виде случайных, необъяснимых ошибок, когда несовместимые экземпляры классов рассматриваются как совместимые из-за фиксированного serialVersionUID. Удаленные вызовы будут молча работать во время низкоуровневой сериализации, и проблема возникнет только позже, когда состояние вашего объекта будет несовместимым. Вы обнаружите источник проблемы только тогда, когда поймете, что классы вашего клиента и сервера чем-то отличаются (хотя serialVersionUID, конечно, нет). По моему опыту установка serialVersionUID по этой причине приносит больше вреда, чем пользы.
Если, с другой стороны, вы явно настроили serialVersionUID для чтения старых данных, вы по определению читаете в несовместимой версии и, скорее всего, в конечном итоге получите объект в несогласованном или неполном состоянии. В этом случае настройка serialVersionUID является обходным решением для другой проблемы.
Идете ли вы за serialVersionUID
или нет (я предлагаю вам сделать), тогда вы действительно должны подумать о создании всеобъемлющего набора тестов для последовательной совместимости.
Также стоит тщательно разработать серийный формат. Это по сути публичный API.