Использовать serialVersionUID или подавлять предупреждения?

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

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

Ответ 1

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

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

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

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

Ответ 2

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

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

Ответ 3

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

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

Ответ 4

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

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

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

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

Надеюсь, что Стив означал:)

Ответ 5

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

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

Ответ 6

Пусть Eclipse генерирует идентификатор. Быстро и просто. Предупреждения нельзя игнорировать. Также сэкономит много неприятностей, если вы когда-нибудь дойдете до точки, где объект/должен/быть сериализован.

Ответ 7

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

Ответ 8

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

Ответ 9

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

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

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

Ответ 11

Это зависит.

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

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

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

Ответ 12

Если вы знаете, что ваши приложения никогда не сериализуют что-то, подавляйте предупреждение в масштабе всей программы. Это можно сделать с помощью аргументов командной строки javac:

javac -Xlint -Xlint:-serial *******

Таким образом у вас появятся все предупреждения, кроме "serial". IDE файлы и инструменты сборки, такие как Maven/SBT/ Gradle, отлично работают с этим.