Использовать serialVersionUID или подавлять предупреждения? - PullRequest
66 голосов
/ 29 сентября 2008

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

Что бы вы сделали и почему?

Ответы [ 12 ]

27 голосов
/ 29 сентября 2008

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

В противном случае кто-то может в будущем сериализовать ваш объект через родительский класс и получить сериализованную форму по умолчанию, где:

  • форма не совместима между различными версиями вашего кода.
  • вы подавили предупреждение, что это так.

Добавление идентификатора звучит как ложь, так как то, что вы действительно хотите сделать, это не сериализовать. Ожидание, что вызывающие абоненты не сериализуют ваш объект, означает, что вы ожидаете, что они «узнают», когда их HttpServlet относится к вашему классу. Это нарушение полиморфизма лежит на вашей голове за наличие сериализуемого объекта, который не должен быть сериализован, и самое меньшее, что вы можете сделать, - это убедиться, что неосторожные абоненты знают об этом.

18 голосов
/ 29 сентября 2008

Если вы не планируете сериализацию экземпляров, добавьте SuppressWarning.

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

14 голосов
/ 29 сентября 2008

Я отказываюсь от того, что Eclipse терроризирует меня, чтобы добавить беспорядок в мой код!

Я просто настраиваю Eclipse, чтобы он не генерировал предупреждения об отсутствующем serialVersionUID.

9 голосов
/ 14 мая 2010

Спасибо @ Стиву Джессопу за ответ на этот вопрос. Это было 5 строк кода ... вряд ли хлопот.

Я добавил @SuppressWarnings("serial") чуть выше рассматриваемого класса.

Я также добавил этот метод:

private void writeObject(ObjectOutputStream oos) throws IOException {
   throw new IOException("This class is NOT serializable.");
}

Надеюсь, это и имел в виду Стив:)

6 голосов
/ 29 сентября 2008

Даже если вы знаете, что этот объект будет сериализован, вам не нужно генерировать serialVersionUID, потому что java автоматически сгенерирует его для вас и будет автоматически отслеживать изменения, поэтому ваша сериализация всегда будет работать нормально. Вы должны генерировать его, только если знаете, что делаете (обратная совместимость сериализации, отслеживание изменений вручную и т. Д.)

Таким образом, я бы сказал, что подавление предупреждения является лучшим и наиболее безопасным решением в большинстве случаев.

3 голосов
/ 29 сентября 2008

Хорошо генерировать SVUID для каждого класса, реализующего сериализуемый. Причина проста. Вы никогда не знаете, когда он будет сериализован вами или какой-либо третьей стороной. Там можно настроить множество сервисов, которые будут сериализовать сервлеты. Для каждой IDE существует плагин, который генерирует один или просто использует шаблон и устанавливает svuid = 1L.

3 голосов
/ 29 сентября 2008

Это предупреждение сводит меня с ума, потому что каждый раз, когда вы наследуете класс Swing, вы знаете , что вы никогда не собираетесь его сериализовать, но есть это глупое предупреждение. Но да, я позволил Eclipse создать один.

2 голосов
/ 08 июня 2011

Это зависит.

Если вы используете разные компиляторы для компиляции исходного кода несколько раз, ваш скомпилированный код может иметь разные serializationId, которые нарушат сериализацию. Затем вам нужно придерживаться постоянного serializationId в вашем коде. Он должен быть статическим, конечным и для каждого класса (не наследуемым).

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

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

2 голосов
/ 17 марта 2009

Пожалуйста, перейдите по этой ссылке, чтобы получить подробное объяснение: http://technologiquepanorama.wordpress.com/2009/02/13/what-is-use-of-serialversiouid/

2 голосов
/ 29 сентября 2008

Если вы не укажете serialVersionUID, java сгенерирует его для класса во время компиляции (он меняется при каждой компиляции).

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

Я всегда использую 1L для serialversionUID. Это не повредит (по сравнению с сгенерированным по умолчанию) и все еще оставляет возможность нарушать совместимость позже, увеличивая id.

...