Подтвердить что ты не робот

Явный serialVersionUID считается вредным?

Я, вероятно, рискую некоторыми понижениями на этом.

Мне кажется, что явно специфицировать serialVersionUID для новых классов плохо. Рассмотрим два случая не изменять его, когда макет должен быть изменен и изменить его, когда он не должен иметь.

Не меняется, когда оно должно быть изменено, происходит почти только в том случае, если оно явное. В этом случае это приводит к некоторым очень тонким, труднодоступным ошибкам. Особенно во время разработки, когда макет класса меняется часто. Но если он не был явно определен, он изменится, и десериализация будет громко ломаться, в основном, вероятно, решена путем очистки хранилища.

Изменение, когда оно не должно происходить, происходит почти только тогда, когда оно неявно. Это редкий случай, когда макет класса изменился, но мы все еще хотим десериализовать старые сериализованные капли. Вероятно, это будет обнаружено во время QA (Странные ошибки после обновления с 5.2 до 5.2.1, см. Прилагаемую трассировку стека) и могут быть тривиально зафиксированы путем установки явного значения.

Комментарии?

4b9b3361

Ответ 1

Изменение, когда это не должно происходить по причинам, отличным от изменений макета класса, - проблема в том, что реализация компилятора зависит от него. Если вы выполняете отладку с Eclipse, но выполняете сборку сборки с помощью javac, вы можете получить два несовместимых набора данных.

Ответ 2

В моей работе мы явно запрещаем указывать serialVersionUID, именно из-за проблем, которые вы вызываете.

Кроме того, сохраняемые нами классы используются только для хранения данных без внутренней логики, поэтому единственный способ их изменения заключается в изменении членов данных.

Ответ 3

чтобы еще раз подчеркнуть, что сказал Джон Скит и противоречить комментарию:

"Если вам это не нужно (т.е. вы всегда сериализуете и де-сериализуете с той же версией класса), вы можете безопасно пропустить явное объявление"

Даже если вы не используете сериализацию в долгосрочной перспективе и используете ту же версию класса, вы все равно можете иметь проблемы. если вы пишете код клиент-сервер, а клиентский код может запускаться с другой версией/реализацией jvm, чем сервер, у вас могут быть те же проблемы с несовместимыми serialversionuids.

Подводя итог, только время, когда "безопасно" не указывать serialversionuids, - это когда вы не сериализуете долгосрочные, и вам гарантировано, что все потребители сериализованных данных будут использовать одинаковые jvm и версия как оригинальный производитель.

короче говоря, не используя serialversionuid - это, как правило, более вредная ситуация.

Ответ 4

Когда вам нужно поддерживать долговременную настойчивость с помощью сериализации, вам почти всегда нужно использовать собственный код для поддержки этого и нужно явно установить serialVersionUID, поскольку в противном случае более старая сериализованная версия не будет де-сериализуема более новыми код.

Эти сценарии уже требуют большой осторожности, чтобы все правильные случаи, когда класс изменяется, поэтому serialVersionUID является наименьшей из ваших проблем.

Если вам это не нужно (т.е. вы всегда сериализуете и де-сериализуете с той же версией класса), тогда вы можете безопасно пропустить явное объявление, так как вычисленное значение будет гарантировать, что используется правильная версия.

Ответ 5

Если вы идете на serialVersionUID или нет (я предлагаю вам это делать), тогда вам действительно стоит подумать о создании всеобъемлющего набора тестов для обеспечения совместимости серий.

Также стоит с осторожностью разрабатывать серийный формат. Это общедоступный API.

Ответ 6

Если вы используете сериализацию для удаленного вызова метода, например. вызывая EJB, где классы клиента и сервера и jvm одинаковы, что, как я подозреваю, на сегодняшний день является наиболее распространенным использованием, поэтому явное определение serialVersionUID (как, например, eclipse), может вызвать у вас значительную боль в виде случайных, необъяснимые ошибки, когда несовместимые экземпляры классов рассматриваются как совместимые из-за фиксированного serialVersionUID. Удаленные вызовы во время низкоуровневой сериализации будут ошибочно ошибаться, и проблема будет возникать позже, когда состояние вашего объекта будет непоследовательным. Вы обнаруживаете источник проблемы только тогда, когда понимаете, что ваш клиент и серверные классы каким-то образом отличаются (хотя serialVersionUID, конечно, нет). По моему опыту установка serialVersionUID по этой причине приносит больше вреда, чем пользы.

Если, с другой стороны, вы явно задаете serialVersionUID для чтения в старых данных, вы по определению читаете в несовместимой версии и, вероятно, попадете в объект в несогласованном или неполном состоянии. В этом случае установка serialVersionUID является обходным решением для другой проблемы.