JavaRush /Java блог /Random UA /У відповідь на статтю "Навіщо використовувати SerialVersi...
Сергей
31 рівень
Киев

У відповідь на статтю "Навіщо використовувати SerialVersionUID всередині Serializable класу в Java"

Стаття з групи Random UA
Отже.. Маємо клас, який хочемо серіалізувати звичайними методами (використовуємо 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;
}
Круто .. все продовжує працювати. Ось і закінчив свою першу статтю. Я все це хотів вкласти в коментарі, але не проліз символами. Прийму тверезу критику і зауваження PS Дякуємо автору, який спонукав мене на ці вишукування.
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ