IntelliJ IDEA, генерирующий serialVersionUID

297

Как сгенерировать это значение в IntelliJ IDEA?

Я иду в Настройки -> Ошибки -> Проблемы с сериализацией -> Сериализуемый класс без 'serialVersionUID', но он все равно не показывает мне предупреждение. Мой класс PKladrBuilding реализует интерфейс Serializable .

Часть кода:

public class PKladrBuilding extends PRQObject

public abstract class PRQObject extends PObject

public abstract class PObject implements Serializable
Кирилл Базаров
источник
3
Вы уверены, что вам нужно генерировать значение, а не определять свое? Если вы создаете новый класс, я бы порекомендовал вам определить, например, 1Lкак ваш идентификатор и приращение при изменении вашей сериализованной формы. (См. Stackoverflow.com/questions/888335/… ).
Дункан Джонс
1
stackoverflow.com/questions/24573643/… имеет очень хорошее решение.
Панкадж Кумар

Ответы:

589

Я не уверен, что у вас есть старая версия IntelliJ IDEA, но если я зайду в меню ФайлНастройки ...ПроверкиПроблемы с сериализацией → Сериализуемый класс без включенного «serialVersionUID», то класс, который вы предоставляете, дает мне предупреждения.

Введите описание изображения здесь

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

Введите описание изображения здесь

Кстати: он не показывал мне предупреждение, пока я не добавил { }в конец каждого класса, чтобы исправить ошибку компиляции.

Питер Лори
источник
2
Попробуй File| Invalidate Caches, если это не поможет, свяжитесь с support@jetbrains.com с примером проекта для воспроизведения.
CrazyCoder
1
Проверьте idea.log(Help | Reveal Log in ...) на наличие исключений: известно, что зашифрованный домашний каталог в Linux вызывает проблемы из-за ошибки в ядре .
CrazyCoder
1
у меня есть много исключений там .. как java.lang.NoClassDefFoundError: org / intellij / lang / annotations / MagicConstant;
Кирилл Базаров
2
Я переустановил IDEA и удалил плагины, и это помогает мне. TNX много.
Кирилл Базаров
5
В v15 я работал так, чтобы навести курсор на ClassName, чтобы увидеть предупреждение, и медленно переместить мою мышь к желобу. В этот момент «лампочка» появляется на экране. (Попробуйте несколько раз, если это не работает, как задумано в первый раз). Затем вы можете нажать на опцию создания поля, чтобы создать UID. Надеюсь, что это помогает людям, которые застряли на этом.
Нияз
173

Установите плагин GenerateSerialVersionUID от Оливье Дескью.

Перейдите: меню ФайлНастройкиПлагиныОбзор репозиториевGenerateSerialVersionUID

Установите плагин и перезапустите.

Теперь вы можете сгенерировать идентификатор из меню CodeGenerate → serialVersionUID` или ярлыка.

Sileria
источник
14
Нужно ли действительно внешний плагин, чтобы это заработало?
Х.Раби
Да, вам нужен плагин, который уже является частью репозитория плагинов IntelliJ.
Sileria
Работал для меня на Intellij IDEA 12.1
Сагар Хатекар
У меня работает на 13.0.2.
user1978019
Работает на Android Studio 0.8.9
Итай
67

Без каких-либо плагинов: вам просто нужно включить подсветку в IntelliJ:

IntelliJ Preferences -> Editor -> Inspections -> Java -> Serialization issues -> Serializable class without 'serialVersionUID'- установите флаг и нажмите 'OK'.

Теперь, если ваш класс реализует Serializable, вы увидите выделение, а alt+Enterпо имени класса предложите сгенерировать private static final long serialVersionUID.

PS: взято отсюда

Нихил Катре
источник
4
Спасибо. Я не знаю, почему я не вижу лампочку, но щелчок по имени класса и ввод Alt-Enter делает свое дело.
Джон С
2
Отсюда
Сергей Максимчук
это более актуально
Кристиан Мэтью
39

Потратив некоторое время на сериализацию, я обнаружил, что мы не должны генерировать serialVersionUIDс каким-то случайным значением, мы должны придать ему значимое значение.

Вот подробный комментарий по этому вопросу. Я справляюсь с комментарием здесь.

На самом деле, вы не должны «генерировать» серийные версии UID. Это глупая «особенность», которая проистекает из общего недопонимания того, как этот идентификатор используется Java. Вам следует давать этим идентификаторам значимые, читаемые значения, например, начиная с 1L, и увеличивать их каждый раз, когда вы думаете, что новая версия класса должна сделать все предыдущие версии (которые могли быть ранее сериализованы) устаревшими. Все утилиты, которые генерируют такие идентификаторы, в основном делают то, что делает JVM, когда идентификатор не определен: они генерируют значение на основе содержимого файла класса, следовательно, получают нечитаемые бессмысленные длинные целые числа. Если вы хотите, чтобы каждая версия вашего класса отличалась (в глазах JVM), вам даже не следует указывать значение serialVersionUID, если только JVM создаст его на лету, и ценность каждой версии вашего класса будет уникальной. Целью явного определения этого значения является указание механизму сериализации обрабатывать разные версии класса, имеющие одинаковый SVUID, как если бы они были одинаковыми, например, не отклонять старые сериализованные версии. Итак, если вы определяете идентификатор и никогда не меняете его (и я предполагаю, что это то, что вы делаете, поскольку вы полагаетесь на автогенерацию, и вы, вероятно, никогда не пересоздаете свои идентификаторы), вы гарантируете, что все - даже абсолютно разные - версии ваш класс будет считаться тем же механизмом сериализации. Это то, что вы хотите? Если нет, и если вы действительно хотите контролировать то, как распознаются ваши объекты, вы должны использовать простые значения, которые вы сами можете понять и легко обновить, когда решите, что класс значительно изменился.

Надеюсь это поможет. Удачи.

Эмдадул Савон
источник
2
Спасибо, я так долго пропускал этот простой факт!
Dedek
1
Я бы на самом деле сгенерировал serialVersionUIDбы новое случайное число, если я не хочу поддерживать старые версии при десериализации. Возможно, мне не нужно использовать случайные числа, но я могу начать с 1 и увеличивать его. Тем 3Lне менее, не имеет больше значения для меня тогда -3518231192373568183L. Поэтому, я думаю, оба решения работают одинаково. Случайное число может иметь преимущество в том, что оно просыпается в нелинейных историях с вилками и ветвями.
JojOatXGME
16

Для генерации стоимости используйте

private static final long serialVersionUID = $randomLong$L;
$END$

и предоставьте переменную шаблона randomLong со следующим значением: groovyScript ("new Random (). nextLong (). abs ()")

https://pharsfalvi.wordpress.com/2015/03/18/adding-serialversionuid-in-idea/

pharsfalvi
источник
1
люблю этот комментарий, используя живые шаблоны, это, безусловно, самое быстрое и наиболее настраиваемое решение (например, я удалил символ новой строки). Для настройки перейдите в Android Studio> «Установки»> «Редактор»> «Живые шаблоны» и создайте там новый (значок «плюс») с этим значением и используйте переменные редактирования для входа в скрипт
hcpl
13

Кроме того, вы можете добавить живой шаблон, который будет делать эту работу.

Для этого нажмите Ctrl+Alt+S-> "Live Templates"раздел -> other(или по желанию)

А затем создайте новый с таким определением:

private static final long serialVersionUID = 1L;
$END$

Затем выберите definitionобласть и сохраните ее как'serial'

Теперь вы можете ввести serialTABтело класса.

fallens4e
источник
3

Другой способ создания serialVersionUID - использовать >Analyze >Run Inspection by Nameиз контекстного меню (или сочетания клавиш, которое по умолчанию ctrl+ alt+ shift+ i), а затем ввести «Serializable class без« serialVersionUID »» (или просто ввести «serialVersionUID» и тип вперед. Функция найдет его для вас.

Идея> Анализ> Запустить проверку по имени Затем вы получите контекстное меню, в котором вы можете выбрать, где проводить проверки (например, все из определенного модуля, всего проекта, одного файла, ...)

При таком подходе вам даже не нужно устанавливать общие правила проверки.

Александр
источник
Хорошо, это сделало всю работу за меня. Он нашел отсутствующую переменную и предоставил возможность добавить ее.
arenaq
@arenaq рад, что это помогло кому-то еще ;-)
Александр
2

С версией v2018.2.1

Перейти к

Предпочтения> Редактор> Инспекции> Java> Проблемы с сериализацией> переключить «Сериализуемый класс без« serialVersionUID »».

Предупреждение должно появиться рядом с объявлением класса.

YLyu
источник
1

Я использую Android Studio 2.1, и у меня есть лучшая последовательность получения лампочки, нажав на имя класса и наведя на него курсор на секунду.

Джонни Ву
источник
1

Добавьте живой шаблон с именем ser в другую группу, установите для него значение «Применимо в Java: объявление» и снимите флажок «Сократить имена FQ». Дайте ему текст шаблона просто:

$serial$

Теперь отредактируйте переменные и задайте для serial:

groovyScript("(System.env.JDK_HOME+'/bin/serialver -classpath '+com.intellij.openapi.fileEditor.FileDocumentManager.instance.getFile(_editor.document).path.replaceAll('/java/.*','').replaceAll('/src/','/build/classes/')+' '+_1).execute().text.replaceAll('.*: *','')",qualifiedClassName())

Предполагается стандартная компоновка проекта Gradle. Изменить / построить / на / цель / для Maven.

Грег Аллен
источник
1

Самый простой современный метод: Alt+ Enterна

private static final long serialVersionUID = ;

IntelliJ подчеркнет пространство после =. наведите на него курсор и нажмите alt+ Enter( Option+ Enterна Mac). Вы получите всплывающее окно с надписью «Произвольно изменить инициализатор serialVersionUID». Просто нажмите Enter, и он заполнит это место случайным длинным.

jeremysprofile
источник
0

Если вы хотите добавить отсутствующий 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=${f//\//.}
    clazz=${clazz/%.java/}
    seruidstr=$(serialver -classpath $ic_api_cp $clazz | cut -d ':' -f 2 | sed -e 's/^\s\+//')
    perl -ni.bak -e "print $_; printf qq{%s\n}, 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, в первую очередь, при сохранении совместимости со старыми классами.

schnell18
источник