Почему существует поле serialVersionUID?

С момента запуска интерфейса Serializable меня озадачило, почему я должен включать это поле во все свои классы. Я понимаю, что этому интерфейсу нужен уникальный идентификатор для обозначения класса, но почему они не могут сгенерировать его во время выполнения. Например, они могут сгенерировать его, используя хэш MD5 полного имени класса или аналогичную методологию, используемую для обработки дубликатов в их редких случаях (что, я уверен, делает eclipse, когда его просят сгенерировать идентификатор в любом случае).

Итак, что я спрашиваю (нет, этот пост не просто разглагольствование против стандартной библиотеки), как именно поле сериализации используется фреймворком?

Причина, по которой я хотел бы знать, потому что я собираюсь попытаться создать Aspect (на AspectJ или другом языке), который добавит поле serialVersionUID с использованием хэша MD5 и сможет обрабатывать коллизии способом, приемлемым для API.

О результатах отпишусь, если получится.


person nikdeapen    schedule 07.09.2012    source источник
comment
Меня сбил с толку запуск интерфейса Serializable Под «запуском» DYM Java 1.1? Это долгое время..   -  person Andrew Thompson    schedule 07.09.2012


Ответы (4)


Поле serialVersionUID не обязательно. Если вы его не предоставите, Java создаст его на основе полей и методов вашего класса.

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

public class Person implements Serializable {
    private String name;
    public String getName() {
        return name;
    }
}

serialVersionUID не указано. Если вы запустите serialver Person, он вернет:

Person:    static final long serialVersionUID = 3793453319058452486L;

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

public class Person implements Serializable {
    private String name;
    public String getName() {
        return name;
    }
    public Object foo() {
        return "bar";
    }
}

Сериализованный двоичный файл по-прежнему полностью совместим со старой версией, но serialVersionUID отличается:

Person:    static final long serialVersionUID = -6188734029437600310L;

С другим serialVersionUID десериализация приведет к ошибке несоответствия serialVersionUID. Обходной путь заключается в том, чтобы объявить свой собственный serialVersionUID, установив для него любое значение (я установил его 1L) и изменяя его всякий раз, когда поля изменяются.

Также см. этот связанный с для более подробного обсуждения.

person Steve Kuo    schedule 07.09.2012
comment
вы можете подчеркнуть, что значение не обязательно должно быть уникальным в какой-либо форме или форме. - person jtahlborn; 07.09.2012

почему я должен включать это поле во все свои занятия

Вы не знаете.

почему они не могут генерировать это во время выполнения

Они есть, если только вы не предоставите их сами.

Я попытаюсь создать Aspect (на AspectJ или другом языке), который добавит поле serialVersionUID с использованием хэша MD5.

Это было бы бессмысленно. Вы не понимаете, для чего это. Генерация во время выполнения — это то, что уже происходит по умолчанию, поэтому ваше предложение не добавляет никакой ценности. Значение приходит при указании его во время компиляции, чтобы поглотить незначительные изменения класса, которые фактически не нарушают совместимость версий объекта. Вы не можете сделать это через АОП. Это кодовое решение.

person user207421    schedule 07.09.2012

Интерфейс Serializable

Этот интерфейс существует в пакете java.io. Это реализовано для защиты незначительных изменений и реализовано, чтобы позволить пользователю write и save объекты во время выполнения. Этот интерфейс реализуется всеми Swing-компонентами, поскольку разработчик может расширить их, чтобы JVM могла найти новую версию компонента, т. е. Your class.

SerialVersionUID

serialVersionUID используется в качестве контроля версий в классе Serializable. Если вы явно не объявляете serialVersionUID, JVM will did it for you automatically, на основе различных аспектов вашего класса Serializable, как описано в Java(TM) Object Serialization Specification

person Sri Harsha Chilakapati    schedule 07.09.2012

Как упомянул @Steve Kuo, не обязательно иметь поле serialVersionUID.

Это расстраивает, так как это не является частью контракта для сериализации объекта, около половины разработчиков в нашей команде делают это, а другая половина — нет. Большинство из них обычно просто устанавливают private static final long serialVersionUID = 1L; (хотя некоторым разработчикам нравится использовать это как возможность попробовать свои силы в создании псевдослучайных Лонгов...)

При этом я всегда понимал, что это рудиментарная попытка создания версий Serializable объектов.

Допустим, у нас есть:

public class PersonDTO implements Serializable {

    private static final long serialVersionUID = 1L;

    private String firstName;
    private String lastName;

    // Appropriate getters/setters of course
}

а позже мы должны были добавить новое поле, private String middleInitial.

Если бы мы увеличили значение serialVersionUID до 2, мы могли бы использовать это, чтобы указать, что класс изменился, и старые уже сериализованные экземпляры PersonDTO с serialVersionUID не могут быть десериализованы с этим измененным определением класса.

person Philip Tenn    schedule 07.09.2012
comment
Можно привести доводы в пользу не указания serialVersionUID именно потому, что люди не меняют значение при изменении полей. Обычно я не указываю serialVersionUID, если только мое приложение не будет работать с разными версиями сериализованного двоичного файла. Вы всегда можете определить исходное автоматически сгенерированное значение serialVersionUID, используя serialver. Я отключаю отсутствующее предупреждение serialVersionUID в Eclipse. - person Steve Kuo; 07.09.2012
comment
Здесь несколько заблуждений. Добавление поля не нарушает совместимость сериализации. Таким образом, на самом деле вы не должны изменять значение serialVersionUID в этом случае: все, что вы делаете, это вызывает отсутствие несовместимости. Нет ничего плохого в использовании значения 1 или -1, если оно существует с самого начала жизни класса. - person user207421; 07.09.2012
comment
Это очень хороший момент. Как я уже сказал, это расстраивает, так как разные разработчики относятся к этому по-разному. Я также лично не стал бы полагаться на это или выступать за использование в качестве механизма управления версиями, я просто пытался объяснить, каково мое понимание возможного использования. - person Philip Tenn; 07.09.2012
comment
Итак, добавление поля безопасно с использованием того же serialVersionUID. Но если я вспомню, что изменение или удаление полей небезопасно с использованием одного и того же serialVersionUID. - person Steve Kuo; 07.09.2012
comment
@SteveKuo Добавление, удаление и изменение порядка полей безопасно. Изменение их типов или цепочки наследования классов или его имени или пакета не является. Все это задокументировано в главе Об управлении версиями объектов Спецификация сериализации объектов. - person user207421; 07.09.2012