Топ-100Контроль совместимости классов с помощью SerialVersionUID - CodOrbits
LogoCodOrbits

Раздел: Сериализация

Узнайте, как сериализовать и десериализовать объекты в Java для сохранения состояния и передачи данных.

Все разделы
Иконка Сериализация

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

Last updated: 7 мая 2025 г.

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

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

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

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

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

Search Icon

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

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

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

1import java.io.*;
2import java.util.*;
3
4class Person implements Serializable {
5    // Устанавливаем serialVersionUID в статическое значение 123L.
6    private static final long serialVersionUID = 123L;
7
8    private String name;
9    private int age;
10    private double height;
11    private boolean married;
12    private int IQ; // это поле будет убрано при десериализации
13                    // для демонстрации пользы статического значения SerialVersionUID
14
15    Person(String n, int a, double h, boolean m, int iq) {
16        name = n;
17        age = a;
18        height = h;
19        married = m;
20        IQ = iq;
21    }
22
23    String getName() { return name; }
24    int getAge() { return age; }
25    double getHeight() { return height; }
26    boolean getMarried() { return married; }
27    int getIQ() { return IQ; }
28}
29
30public class SerUid {
31    public static void main(String[] args) {
32        // Сериализуем
33        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.dat"))) {
34            Person p = new Person("Sam", 33, 178, true, 10);
35            // сериализуем класс (у него serialVersionUID = 123L)
36            oos.writeObject(p);
37        } catch (Exception ex) {
38            System.out.println(ex.getMessage());
39        }
40    }
41}

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

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

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

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

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

1import java.io.*;
2import java.util.*;
3
4class Person implements Serializable {
5    // все еще 123L как и раньше.
6    private static final long serialVersionUID = 123L;
7
8    private String name;
9    private int age;
10    private double height;
11    private boolean married;
12    // как видим поля ID больше здесь нет
13
14    Person(String n, int a, double h, boolean m) {
15        name = n;
16        age = a;
17        height = h;
18        married = m;
19    }
20
21    String getName() {
22        return name;
23    }
24
25    int getAge() {
26        return age;
27    }
28
29    double getHeight() {
30        return height;
31    }
32
33    boolean getMarried() {
34        return married;
35    }
36}
37
38public class SerUid {
39    public static void main(String[] args) {
40        // десериализация
41        try (ObjectInputStream ois = new ObjectInputStream(
42                new FileInputStream("person.dat"))) {
43            // десериализуем объект
44            // класса с теперь уже удаленным полем IQ
45            // (serialVersionUID у класса
46            // десериализуемого объекта
47            // все еще 123L поэтому считать
48            // поля которые были в прошлой версии класса,
49            // то есть все кроме IQ можно)
50            Person p = (Person) ois.readObject();
51            System.out.printf(
52                    "Name: %s \t Age: %d \t Height: %f \t Married: %b",
53                    p.getName(), p.getAge(), p.getHeight(),
54                    p.getMarried());
55        } catch (Exception ex) {
56            System.out.println(ex.getMessage());
57        }
58    }
59}

Вывод:


Следующие уроки

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

8
мин.

Similar Articles Icon
Divider

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

10
мин.

Similar Articles Icon
Divider

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

13
мин.

Similar Articles Icon