Итак.. Имеем класс, который хотим сериализовать обычными методами (используем
Serializable
)
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. Спасибо автору, который сподвиг меня на эти изыски.. Наверное, так и учатся :)
Всем успехов :)
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
почтивсе всегда пишут = 1L ответ нашел тут