Java: как создать serialVersionUID
Существует три способа генерации serialVersionUID для вашего класса сериализации.
1. Серийная команда
JDK имеет встроенную команду под названием « serialver ”Для генерации serialVersionUID автоматически. В этом примере вы используете «serialver» для генерации serialVersionUID для класса Address.
E:workspacetargetclasses>serialver Address Address: static final long serialVersionUID = -687991492884005033L;
2. Используйте Eclispe IDE
Если вы используете Eclipse, наведите указатель мыши на класс сериализации.

Или нажмите на класс сериализации и нажмите « CTRL + 1 «.
3. Все, что вы хотите
Просто укажите свой собственный serialVersionUID, дайте номер и добавьте «L» позади.
private static final long serialVersionUID = 1L;
В ответ на статью «Зачем использовать SerialVersionUID внутри Serializable класса в Java»


Итак.. Имеем класс, который хотим сериализовать обычными методами (используем Serializable )
package Serialization; import java.io.Serializable; public class SerializableClass implements Serializable
Пишем тестовое приложение. Сразу оговорюсь, что моя цель показать, что нам дает 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
Ой. Что-делать.
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
Т.е. мы не даем Java самой высчитывать serialVersionUID на основании своих алгоритмов (довольно сложных алгоритмов). Теперь при любом изменении класса у нас serialVersionUID = 1L Проверяем:
public static void main(String[] args) throws IOException, ClassNotFoundException
Работает.. А теперь так:
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. Спасибо автору, который сподвиг меня на эти изыски.. Наверное, так и учатся 🙂 Всем успехов 🙂
Зачем нужен serialVersionUID в Java и как его использовать
При работе со средой разработки Eclipse, разработчики могут столкнуться с таким предупреждением: «The serializable class Foo does not declare a static final serialVersionUID field of type long». Это сообщение говорит о том, что в сериализуемом классе отсутствует поле serialVersionUID.
Что такое serialVersionUID?
В Java, serialVersionUID — это поле, используемое в сериализуемых классах. Это уникальный идентификатор для каждого класса, который используется в процессе десериализации для проверки того, что загруженный класс и оригинальный класс в точности совпадают.
Зачем он нужен?
Без этого поля процесс десериализации может привести к InvalidClassException , если версия класса изменилась между сериализацией и десериализацией. Это может произойти, если были внесены изменения в класс, например, добавлены или удалены поля.
Пример проблемы
Рассмотрим следующий пример:
import java.io.*; class Foo implements Serializable < int x; int y; >public class Main < public static void main(String[] args) < Foo foo = new Foo(); foo.x = 3; foo.y = 4; // Сериализация foo try < ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("foo.ser")); out.writeObject(foo); out.close(); >catch (IOException e) < e.printStackTrace(); >// Изменение класса Foo // . // Десериализация foo try < ObjectInputStream in = new ObjectInputStream(new FileInputStream("foo.ser")); Foo fooRead = (Foo) in.readObject(); in.close(); >catch (IOException | ClassNotFoundException e) < e.printStackTrace(); >> >
Если класс Foo был изменен после сериализации (например, было добавлено новое поле), процесс десериализации может вызвать исключение InvalidClassException .
Как использовать serialVersionUID?
Чтобы избежать этого исключения, можно явно объявить поле serialVersionUID в классе:
class Foo implements Serializable
Это гарантирует, что любые изменения в классе не повлияют на процесс десериализации, если они не изменяют семантику объекта.
Таким образом, serialVersionUID является важным инструментом в обеспечении стабильности и совместимости сериализуемых классов в Java.
Как сгенерировать ID для сериализуемого объекта?
Мне нужно проидентифицировать данные и сериализовать их. Следующий идентификатор не подходит, потому что статические поля не сериализуются:
public class MyClass implements Serializable < private static int inc = 0; private int id; public MyClass() < this.id = inc++; >>
Как лучше всего идентифицировать объекты в таком случае?
Отслеживать
задан 5 ноя 2019 в 17:35
479 1 1 золотой знак 3 3 серебряных знака 15 15 бронзовых знаков
А зачем вам сериализовать значение генератора? Оно же у вас одно на все объекты. А объект у вас идентифицируется полем id
5 ноя 2019 в 17:50
@AntonShchyrov, после перезапуска приложения и десериализации значение генератора обнулится, и при создании объектов он снова будет идентифицировать их, начиная с нуля. Будут объекты с одинаковыми id.
5 ноя 2019 в 17:58
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Вам значение генератора нужно хранить в другом месте. В базе или в файле (в обоих случаях предусмотреть атомарный доступ к генератору).
Или, как вариант, использовать для идентификации UUID
public class MyClass implements Serializable < private UUID id; public MyClass() < this.id = UUID.randomUUID(); >>
Update
Как тут меня поправляют метод randomUUID() стандартного класса UUID генерирует UUID 4 версии. Т.е. случайный набор значений. И хоте вероятность совпадения двух сгенерированных значений мала, но она есть.
Чтобы получить гарантированно уникальный UUID вам нужно генерировать UUID любой другой версии (1, 2, 3, 5). Они базируются на текущем времени и уникальном идентификаторе компьютера.
К сожалению, стандартный класс их генерировать не умеет. Но можно подключить внежнюю библиотеку, которая умеет это делать. Например JUG (java-uuid-generator)