Я, вероятно, рискую проголосовать против этого.
Мне кажется, что явно указывать serialVersionUID для новых классов - это плохо. Рассмотрим два случая: не изменять его, когда макет должен был быть изменен, и изменять его, когда этого не должно было быть.
Невозможность изменения, когда это должно было быть изменено, происходит почти только тогда, когда это явно указано. В этом случае это приводит к очень тонким, трудно обнаруживаемым ошибкам. Особенно во время разработки, когда раскладка классов часто меняется. Но если он не был явно указан, он изменится, и десериализация будет громко прервана, что, скорее всего, будет решено очисткой репозитория.
Его изменение, когда не должно было произойти, произойдет почти только тогда, когда оно неявно. Это тот редкий случай, когда макет класса изменился, но мы все еще хотим десериализовать старые сериализованные большие двоичные объекты. Это, вероятно, будет обнаружено во время QA (Странные ошибки после обновления с 5.2 до 5.2.1, см. Приложенную трассировку стека) и может быть тривиально исправлено путем установки явного значения.
Комментарии?




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