Как сгенерировать 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)
В ответ на статью «Зачем использовать 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. Спасибо автору, который сподвиг меня на эти изыски.. Наверное, так и учатся 🙂 Всем успехов 🙂
IntelliJ IDEA generating serialVersionUID
How do generate this value in IntelliJ IDEA? I go to Settings -> Errors -> Serialization issues -> Serializable class without ‘serialVersionUID’, but it still doesn’t show me the warning. My class PKladrBuilding parent implements interface Serializable. Part of the code:
public class PKladrBuilding extends PRQObject public abstract class PRQObject extends PObject public abstract class PObject implements Serializable
30.8k 22 22 gold badges 106 106 silver badges 131 131 bronze badges
asked Oct 16, 2012 at 10:10
user1679671 user1679671
Are you sure you need to generate a value, rather than defining your own? If you are creating a new class, I would recommend you define e.g. 1L as your ID and increment when your serialized form changes. (See stackoverflow.com/questions/888335/…).
Oct 16, 2012 at 10:15
stackoverflow.com/questions/24573643/… has a very good solution.
Dec 27, 2016 at 7:06
13 Answers 13
I am not sure if you have an old version of IntelliJ IDEA, but if I go to menu File → Settings. → Inspections → Serialization issues → Serializable class without ‘serialVersionUID’` enabled, the class you provide give me warnings.

If I try the first class I see:

BTW: It didn’t show me a warning until I added < >to the end of each class to fix the compile error.
30.8k 22 22 gold badges 106 106 silver badges 131 131 bronze badges
answered Oct 16, 2012 at 10:17
Peter Lawrey Peter Lawrey
528k 81 81 gold badges 762 762 silver badges 1136 1136 bronze badges
Try File | Invalidate Caches , if it doesn’t help, contact [email protected] with a sample project to reproduce.
Oct 16, 2012 at 10:19
Check idea.log (Help | Reveal Log in . ) for exceptions, encrypted home directory on Linux is known to cause problems because of the kernel bug.
Oct 16, 2012 at 10:53
i have a lot of exceptions there.. like java.lang.NoClassDefFoundError: org/intellij/lang/annotations/MagicConstant;
– user1679671
Oct 16, 2012 at 10:58
I have reinstalled IDEA and removed plug-ins and it helps me. Tnx a lot.
– user1679671
Oct 16, 2012 at 12:10
The way I got it working in the v15 is to hover over the ClassName to see the warning and move my mouse slowly towards the gutter. At that point the «lightbulb» shows up on the screen. (Try this a few times if it does not work as intended the first time). Then you can click on the create field option to create the uid. Hope this helps people who are stuck on this.
Jan 14, 2016 at 22:11
Install the GenerateSerialVersionUID plugin by Olivier Descout.
Go to: menu File → Settings → Plugins → Browse repositories → GenerateSerialVersionUID
Install the plugin and restart.
Now you can generate the id from menu Code → Generate → serialVersionUID` or the shortcut.
30.8k 22 22 gold badges 106 106 silver badges 131 131 bronze badges
answered Aug 20, 2013 at 17:29
15.3k 4 4 gold badges 49 49 silver badges 28 28 bronze badges
Should one require an external plugin really in order to get this working?
May 30, 2014 at 21:34
Yes you need a plugin which is already part of IntelliJ plugin repository.
Jun 13, 2014 at 17:09
Timeout for me on Android Studio
Sep 24, 2015 at 8:15
Works in 2017.3.4 — I noticed you could not generate a serialVersionUID when it was defined in a base class (even though it is private static and should not matter in that sense). This plugin just offered the option and works. Nice.
Feb 6, 2018 at 14:57
Answer is correct, but a plugin which breaks every few major version is not as good as using the internal solution also posted here.
Sep 17, 2018 at 13:37
Without any plugins: You just need to enable highlight in IntelliJ:
IntelliJ Preferences -> Editor -> Inspections -> Java -> Serialization issues -> Serializable class without ‘serialVersionUID’ — set flag and click ‘OK’ .
Now, if your class implements Serializable , you will see highlight, and alt+Enter on class name will propose to generate private static final long serialVersionUID .
answered Mar 15, 2017 at 5:29
Nikhil Katre Nikhil Katre
2,174 25 25 silver badges 22 22 bronze badges
Thanks. I don’t know why I don’t see the light bulb, but clicking on the class name and typing Alt-Enter does the trick.
Sep 10, 2018 at 16:51
Answer is stolen from here
Feb 21, 2019 at 10:11
this is more uptodate
Jun 11, 2019 at 18:44
After spending some time on Serialization, I find that, we should not generate serialVersionUID with some random value, we should give it a meaningful value.
Actually, you should not be «generating» serial version UIDs. It is a dumb «feature» that stems from the general misunderstanding of how that ID is used by Java. You should be giving these IDs meaningful, readable values, e.g. starting with 1L, and incrementing them each time you think the new version of the class should render all previous versions (that might be previously serialized) obsolete. All utilities that generate such IDs basically do what the JVM does when the ID is not defined: they generate the value based on the content of the class file, hence coming up with unreadable meaningless long integers. If you want each and every version of your class to be distinct (in the eyes of the JVM) then you should not even specify the serialVersionUID value isnce the JVM will produce one on the fly, and the value of each version of your class will be unique. The purpose of defining that value explicitly is to tell the serialization mechanism to treat different versions of the class that have the same SVUID as if they are the same, e.g. not to reject the older serialized versions. So, if you define the ID and never change it (and I assume that’s what you do since you rely on the auto-generation, and you probably never re-generate your IDs) you are ensuring that all — even absolutely different — versions of your class will be considered the same by the serialization mechanism. Is that what you want? If not, and if you indeed want to have control over how your objects are recognized, you should be using simple values that you yourself can understand and easily update when you decide that the class has changed significantly. Having a 23-digit value does not help at all.
Hope this helps. Good luck.
IntelliJ IDEA генерирует serialVersionUID
Я перехожу в Настройки -> Ошибки -> Проблемы с сериализацией -> Класс Serializable без’serialVersionUID’, но он все еще не показывает мне предупреждение. Мой родительский класс PKladrBuilding реализует интерфейс Serializable.
public class PKladrBuilding extends PRQObject public abstract class PRQObject extends PObject public abstract class PObject implements Serializable
Поделиться Источник 16 октября 2012 в 10:10
13 ответов
Я не уверен, есть ли у вас старая версия IntelliJ IDEA, но если я перейду в меню Файл — Настройки. — Инспекции — Проблемы с сериализацией — Класс сериализации без включения’serialVersionUID’, класс, который вы предоставляете, выдает мне предупреждения.

Если я попробую первый класс, я увижу:

Кстати: Он не показывал мне предупреждение, пока я не добавил < >в конец каждого класса, чтобы исправить ошибку компиляции.
Поделиться 16 октября 2012 в 10:17
Установите плагин GenerateSerialVersionUID от Оливье Дескоута.
Перейдите в: меню Файл — Настройки — Плагины — Репозитории браузера — GenerateSerialVersionUID
Установите плагин и перезапустите.
Теперь вы можете сгенерировать идентификатор из меню Код — Генерировать — serialVersionUID` или ярлык.
Поделиться 20 августа 2013 в 17:29
Без каких-либо плагинов: Вам просто нужно включить выделение в IntelliJ:
Настройки IntelliJ -> Редактор -> Инспекции -> Java -> Проблемы с сериализацией -> Класс Serializable без’serialVersionUID’ — установите флаг и нажмите ‘OK’ .
Теперь, если ваш класс реализует Serializable , вы увидите выделение, и alt+Enter по имени класса предложит сгенерировать private static final long serialVersionUID .
Поделиться 15 марта 2017 в 05:29
После того, как я потратил некоторое время на сериализацию, я обнаружил, что мы не должны генерировать serialVersionUID с каким-то случайным значением, мы должны дать ему значимое значение.
На самом деле, вы не должны «генерировать» UID серийной версии. Это глупая «фича», которая возникает из общего непонимания того, как этот ID используется в Java. Вы должны давать этим ID значимые, читаемые значения, например, начиная с 1L, и увеличивая их каждый раз, когда вы думаете, что новая версия класса должна сделать все предыдущие версии (которые могут быть сериализованы ранее) устаревшими. Все утилиты, которые генерируют такие ID, в основном делают то, что делает JVM, когда ID не определен: они генерируют значение на основе содержимого файла класса, что приводит к нечитаемым бессмысленным длинным целым числам.Если вы хотите, чтобы каждая версия вашего класса была уникальной (в глазах JVM), то вам даже не следует указывать значение serialVersionUID, так как JVM будет производить одну на лету, и значение каждой версии вашего класса будет уникальным. Цель определения этого значения явно заключается в том, чтобы указать механизму сериализации, чтобы обрабатывать разные версии класса, которые имеют одинаковый SVUID, например, чтобы не отклонять более старые сериализованные версии. Поэтому, если вы определяете идентификатор и никогда не изменяете его (и я предполагаю, что это то, что вы делаете, так как полагаетесь на автогенерацию и, вероятно, никогда не будете перегенерировать свои идентификаторы), вы гарантируете, что все — даже абсолютно разные — версии вашего класса будут считаться одинаковыми механизмом сериализации. Это то, что вы хотите? Если нет, и если вы действительно хотите иметь контроль над распознаванием ваших объектов, вы должны использовать простые значения, которые вы сами можете понять и легко обновить, когда решите, что класс значительно изменился.Иметь 23-значное значение совсем не помогает.
Надеюсь, это поможет. Удачи.
Поделиться 16 июля 2017 в 04:53
Самый простой современный метод: Alt + Enter на
private static final long serialVersionUID = ;
IntelliJ подчеркнет пробел после = . Нажмите на него свой курсор и нажмите alt + Enter ( Option + Enter на Mac). Вы получите всплывающее окно с сообщением «Случайно измените инициализатор serialVersionUID». Просто нажмите Enter, и оно заполнит это пространство случайной длинной.
Поделиться 06 мая 2020 в 17:46
Для генерации значения используйте
private static final long serialVersionUID = $randomLong$L; $END$
и предоставьте переменной шаблона randomLong следующее значение: groovyScript(«new Random().nextLong().abs()»)
Поделиться 18 марта 2015 в 10:01
Кроме того, вы можете добавить живой шаблон, который будет делать работу.
Чтобы сделать это, нажмите Ctrl+Alt+S -> раздел «Живые шаблоны» -> другой (или вы хотите)
Затем создайте новый с определением, подобным этому:
private static final long serialVersionUID = 1L; $END$
Затем выберите область определения и сохраните ее как ‘серийный’
Теперь вы можете ввести серийный TAB в теле класса.
Поделиться 18 сентября 2014 в 11:59
Другой способ сгенерировать serialVersionUID — использовать >Анализ >Запуск проверки по имени из контекстного меню (или сокращенного сочетания клавиш, которое по умолчанию ctrl + alt + shift + i ) и затем ввести «Сериализуемый класс без’serialVersionUID'» (или просто введите «serialVersionUID», и функция ввода будет находить его за вас.
Это предполагает стандартную верстку проекта Gradle. Измените /build/ на /target/ для Maven.
Поделиться 08 февраля 2017 в 13:01
Я использую Android Studio 2.1 и у меня больше последовательности в получении лампочки, нажав на класс Name и наведя курсор на него на секунду.
Поделиться 27 июня 2016 в 04:10
Если вы хотите добавить отсутствующий serialVersionUID для множества файлов, IntelliJ IDEA может не работать очень хорошо. Я придумал простой скрипт для выполнения этой цели с легкостью:
base_dir=$(pwd) src_dir=$base_dir/src/main/java ic_api_cp=$base_dir/target/classes while read f do clazz=$ clazz=$ seruidstr=$(serialver -classpath $ic_api_cp $clazz | cut -d ':' -f 2 | sed -e 's/^\s\+//') perl -ni.bak -e "print $_; printf qq, q < private $seruidstr>if /public class/" $src_dir/$f done
Вы сохраняете этот скрипт, например, как add_serialVersionUID.sh в папке ~/bin . Затем запускаете его в корневом каталоге вашего проекта Maven или Gradle, например:
add_serialVersionUID.sh < myJavaToAmend.lst
Этот.lst включает список файлов Java для добавления serialVersionUID в следующем формате:
com/abc/ic/api/model/domain/item/BizOrderTransDO.java com/abc/ic/api/model/domain/item/CardPassFeature.java com/abc/ic/api/model/domain/item/CategoryFeature.java com/abc/ic/api/model/domain/item/GoodsFeature.java com/abc/ic/api/model/domain/item/ItemFeature.java com/abc/ic/api/model/domain/item/ItemPicUrls.java com/abc/ic/api/model/domain/item/ItemSkuDO.java com/abc/ic/api/model/domain/serve/ServeCategoryFeature.java com/abc/ic/api/model/domain/serve/ServeFeature.java com/abc/ic/api/model/param/depot/DepotItemDTO.java com/abc/ic/api/model/param/depot/DepotItemQueryDTO.java com/abc/ic/api/model/param/depot/InDepotDTO.java com/abc/ic/api/model/param/depot/OutDepotDTO.java
Этот скрипт использует инструмент JDK serialVer. Он идеально подходит для ситуации, когда вы хотите изменить огромное количество классов, у которых нет установленного serialVersionUID, сохраняя совместимость с старыми классами.
Поделиться 27 июня 2015 в 12:19

На macOS вы можете найти, где применимо serialVersionUID .