JavaRush/Java блог/Random/В ответ на статью "Зачем использовать SerialVersionUID вн...
Сергей
31 уровень

В ответ на статью "Зачем использовать SerialVersionUID внутри Serializable класса в Java"

Статья из группы Random
участников
Итак.. Имеем класс, который хотим сериализовать обычными методами (используем Serializable) В ответ на статью "Зачем использовать SerialVersionUID внутри Serializable класса в Java" - 1
package Serialization;

import java.io.Serializable;

public class SerializableClass implements Serializable {
    private String name;
    private int number;
 }
Пишем тестовое приложение. Сразу оговорюсь, что моя цель показать, что нам дает serialVersionUID.
package Serialization;

import java.io.*;

public class MainSerializable {
    final static String FILE_NAME = "c:\\File.dat";

    public static void serialize(Object object) throws IOException {
        FileOutputStream fileOutputStream = new FileOutputStream(FILE_NAME);
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream);

        objectOutputStream.writeObject(object);

        fileOutputStream.close();
        objectOutputStream.close();
    }

    public static Object deserialize() throws IOException, ClassNotFoundException {
        FileInputStream fileInputStream = new FileInputStream(FILE_NAME);
        ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream);

        Object object = objectInputStream.readObject();

        objectInputStream.close();

        return object;
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException {
        SerializableClass serializableClass = new SerializableClass();

        serialize(serializableClass);

        SerializableClass newObject = (SerializableClass) deserialize();
    }
}
Все прекрасно работает. Класс сериализуется в файл FILE_NAME = "c:\\File.dat". Смеркалось... :) Забыли в класс добавить поля. Добавляем:
public class SerializableClass implements Serializable {
    private String name;
    private int number;
    private String FirstName;   // +
    private String LastName;    // +
 }
Вроде все хорошо.. все компилится.. Итак запускаем main, десериализуем класс SerializableClass из файла "c:\\File.dat":
public static void main(String[] args) throws IOException, ClassNotFoundException {
    SerializableClass newObject = (SerializableClass) deserialize();
}
Ой... Что-делать...
Exception in thread "main" java.io.InvalidClassException: Serialization.SerializableClass; local class incompatible: stream classdesc serialVersionUID = 8129437039424566964, local class serialVersionUID = -8271479231760195917
	at java.base/java.io.ObjectStreamClass.initNonProxy(ObjectStreamClass.java:689)
	at java.base/java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1903)
	at java.base/java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1772)
	at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2060)
	at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1594)
	at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:430)
	at Serialization.MainSerializable.deserialize(MainSerializable.java:22)
	at Serialization.MainSerializable.main(MainSerializable.java:30)
В общем все честно. Класс изменился и его serialVersionUID = -8271479231760195917, а сериализованного в файле serialVersionUID = 8129437039424566964. Что теперь делать, как быть? Как создать экземпляр? Выход есть. Нужно в нашем классе объявить: static final long serialVersionUID, которая равна serialVersionUID засеренного :) класса в файле. Т.е. мы сказали, что давай, десериализируся.. ты можешь.. версии то у тебя одинаковые:
package Serialization;

import java.io.Serializable;

public class SerializableClass implements Serializable {
    static final long serialVersionUID = 8129437039424566964L;

    private String name;
    private int number;
    private String FirstName;   // +
    private String LastName;    // +
}
Запускаем... И.. Все работает Как я понял, можно было этой ошибки избежать, если в классе заранее объявить:
public class SerializableClass implements Serializable {
    static final long serialVersionUID = 1L;

    private String name;
    private int number;
}
Т.е. мы не даем Java самой высчитывать serialVersionUID на основании своих алгоритмов (довольно сложных алгоритмов). Теперь при любом изменении класса у нас serialVersionUID = 1L Проверяем:
public static void main(String[] args) throws IOException, ClassNotFoundException {
    SerializableClass serializableClass = new SerializableClass();

    serialize(serializableClass);

    SerializableClass newObject = (SerializableClass) deserialize();
}
Работает.. А теперь так:
public class SerializableClass implements Serializable {
    static final long serialVersionUID = 1L;

    //private String name;
    //private int number;
}
Есть.. А так?
public class SerializableClass implements Serializable {
    static final long serialVersionUID = 1L;
    public int A;
    protected String value;
    //private String name;
    //private int number;
}
Круто.. все продолжает работать. Вот и закончил свою первую статью. Я все это хотел вложить в комменты, но не пролез по символам. Приму трезвую критику и замечания P.S. Спасибо автору, который сподвиг меня на эти изыски.. Наверное, так и учатся :) Всем успехов :)
Комментарии (3)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Стас Пасинков Software Developer в Zipy Master
3 октября 2019, 08:38
я когда-то задался вопросом: зачем вообще придумали эту фичу с айдишником, если почти все всегда пишут = 1L ответ нашел тут
Стас Пасинков Software Developer в Zipy Master
3 октября 2019, 08:40
и еще вот так When should update your serialVersionUID? When your serialization class is updated with some incompatible Java type changes to a serializable class, you have to update your serialVersionUID. For detail about the compatible and incompatible Java type changes to a serializable class, see the Java Object Serialization Specification.
RayFinkle-s-Pilles
Уровень 22
2 октября 2019, 10:46
на intellij idea есть плагин, генерирующий serialVersionUID туц