Контроль совместимости классов в Java с помощью SerialVersionUID

У каждого сериализуемого класса (именно класса, не объекта класса) есть поле SerialVersionUID.

Это числовой идентификатор, который меняется при каждом изменении класса.

Это может быть использовано при сериализации и десериализации.

Допустим у нас есть Serializable класс, объект которого мы сериализовали, а потом а потом в классе этого объекта сделали изменения, и соответственно, изменяется SerialVersionUID класса, и ясное дело десериализовать в объект измененного класса уже не получиться, выйдет ошибка. Чтобы этого избежать можно в сериализуемый класс добавить постоянное статическое значение поля SerialVersionUID, тогда десериализация не выбросит ошибку.

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

Search Icon

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

Давайте, для начала, сериализуем объект класса у которого SerialVersionUID имеет статическое значение.

Пример программы:

import java.io.*; import java.util.*; class Person implements Serializable { // Устанавливаем serialVersionUID в статическое значение 123L. private static final long serialVersionUID = 123L; private String name; private int age; private double height; private boolean married; private int IQ; // это поле будет убрано при десериализации // для демонстрации пользы статического значения SerialVersionUID Person(String n, int a, double h, boolean m, int iq) { name = n; age = a; height = h; married = m; IQ = iq; } String getName() { return name; } int getAge() { return age; } double getHeight() { return height; } boolean getMarried() { return married; } int getIQ() { return IQ; } } public class SerUid { public static void main(String[] args) { // Сериализуем try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(“person.dat”))) { Person p = new Person(“Sam”, 33, 178, true, 10); // сериализуем класс (у него serialVersionUID = 123L) oos.writeObject(p); } catch (Exception ex) { System.out.println(ex.getMessage()); } } }

Скомпилируем и запустим:

Объект сериализован в файл person.dat.

Теперь давайте десериализуем сериализованный объект, но класс Person уже будет изменен.

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

Пример программы:

import java.io.*; import java.util.*; class Person implements Serializable { // все еще 123L как и раньше. private static final long serialVersionUID = 123L; private String name; private int age; private double height; private boolean married; // как видим поля ID больше здесь нет Person(String n, int a, double h, boolean m) { name = n; age = a; height = h; married = m; } String getName() { return name; } int getAge() { return age; } double getHeight() { return height; } boolean getMarried() { return married; } } public class SerUid { public static void main(String[] args) { // десериализация try (ObjectInputStream ois = new ObjectInputStream( new FileInputStream(“person.dat”))) { // десериализуем объект // класса с теперь уже удаленным полем IQ // (serialVersionUID у класса // десериализуемого объекта // все еще 123L поэтому считать // поля которые были в прошлой версии класса, // то есть все кроме IQ можно) Person p = (Person) ois.readObject(); System.out.printf( “Name: %s \t Age: %d \t Height: %f \t Married: %b”, p.getName(), p.getAge(), p.getHeight(), p.getMarried()); } catch (Exception ex) { System.out.println(ex.getMessage()); } } }

Вывод:

Сериализация Singleton без утраты его сути

Узнайте, как сохранить Singleton при сериализации в Java. Метод readResolve гарантирует единственность экземпляра после десериализации.
Time to read: 8

Управляемая сериализация в Java: Externalizable

Как сериализовать объекты с классами, не реализующими Serializable. Используем Externalizable для ручного управления процессом в Java.
Time to read: 10

Базы данных: основные принципы

Основы реляционных баз данных: таблицы, атрибуты и кортежи. Как хранить данные эффективно и избегать избыточности. Пример таблиц.
Time to read: 13