Главная » Java » Контроль версий объектов в Java

0

 

   Реализация классов со временем изменяется. Если подобное происходит в промежутке времени между сериализацией и десериализацией объекта этого класса, поток ObjectlnputStream способен обнаружить факт внесения изменений. При сохранении объекта вместе с ним записывается уникальный идентификатор но мера версии (serial version unique identifier, UID), 64-битовое значение типа 1 ong-По умолчанию идентификатор создается в виде хеш-кода, построенного на осно информации об именах класса, его членов и базовых интерфейсов; изменение ких данных служит сигналом о возможной несовместимости версий класса, код подобен отпечатку пальца — почти невероятно, чтобы два различных класса обладали одинаковым идентификатором номера версии.

   При вводе данных об объекте из потока ObjectlnputStream считывается также и идентификатор номера версии. Затем предпринимается попытка загрузки соответствующего класса. Если требуемый класс не найден либо идентификатор  загруженного класса не совпадает с тем, который считан из потока, метод readObject выбрасывает исключение типа Inval idCl ass Exception. Если успешно загружены все нужные классы и выявлено совпадение всех идентификаторов, объект, как принято считать, может быть подвергнут десериализации.

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

 

private static final   long

          serialversionUID =  -1307795172754062330L;

 

Конкретное значение идентификатора рассчитывается средствами используемой вами среды разработки Java. Во многих случаях его можно получить, обратившись к программе serialver. В других системах предлагаются иные способы вычисления идентификатора. (Ничто не мешает использовать в качестве идентификатора и любое произвольное значение, если оно фиксируется в самой первой версии класса, но обычно это не самое лучшее решение. Вы наверняка не сможете столь же тщательно сгенерировать идентификатор, как это делают стандартные инструменты, и обеспечить его уникальность, чтобы предотвратить возможные конфликты с хеш-кодами других классов.)

  Теперь, когда поток ObjectlnputStream находит описание требуемого класса и сопоставляет его идентификатор с тем, который сохранен вместе с сериализован-ными данными, проблема несовместимости не возникнет, если даже реализация класса на самом деле подверглась изменению. Если вызывается метод riefaultReadObject, будут восстановлены значения только тех полей, которые присутствовали в исходной версии класса, — всем другим полям присваиваются значения, предлагаемые по умолчанию в соответствии с их типами. Если значения полей ранней версии класса были сохранены без использования метода QefaultWriteObject, на этапе сериализации следует обеспечить их чтение. При попытке чтения большего объема данных, чем сохраненный, выбрасывается исключение типа EOFException. Следует проектировать классы таким образом, чтобы прикладная программа могла считывать идентификатор версии класса, а не основывать свои действия на информации, возвращаемой объектом исключения.

  При передаче данных об объекте в поток ObjectOutputStream также сохраняется   и   соответствующий   объект   Class.   Поскольку   содержимое   объектов

зависит  от  реализации  виртуальной  машины,   сериализацию  подобных

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

замещаются объектами ObjectStreamClass, которые содержат всю информа-

10. необходимую для отыскания класса в ходе десериализации его объектов,

лючая полное наименование класса и его уникальный идентификатор номера

версии. Объекты класса ObjectStreamClass никогда не используются напрямую если только вы сами не создаете их непосредственно.

 

Источник: Арнолд, Кен, Гослинг, Джеймс, Холмс, Дэвид. Язык программирования Java. 3-е изд .. : Пер. с англ. – М. : Издательский дом «Вильяме», 2001. – 624 с. : ил. – Парал. тит. англ.

По теме:

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