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/… має дуже хороше рішення.
Панкай Кумар

Відповіді:


588

Я не впевнений, чи є у вас стара версія IntelliJ IDEA, але якщо я перейду до меню ФайлНалаштування ...ІнспекціїПроблеми з серіалізацією → Клас серіалізації без включення "serialVersionUID", клас, який ви надаєте, дає мені попередження.

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

Якщо я спробую перший клас, я бачу:

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

BTW: Мені не було показано попередження, поки я не додав { }до кінця кожного класу, щоб виправити помилку компіляції.


2
Спробуйте File| Invalidate Caches, якщо це не допомагає, зверніться до support@jetbrains.com із прикладом проекту для відтворення.
CrazyCoder

1
Перевірте idea.log(довідка | виявити вхід у систему ...) на винятки, зашифрований домашній каталог в Linux, як відомо, викликає проблеми через помилку ядра .
CrazyCoder

1
у мене там багато винятків .. як java.lang.NoClassDefFoundError: org / intellij / lang / annotations / MagicConstant;
Кирило Базаров

2
Я перевстановив IDEA та видалив плагіни, і це мені допомагає. Tnx багато.
Кирило Базаров

5
Як я отримав це, працюючи в v15, - це навести курсор на ClassName, щоб побачити попередження, і повільно переміщувати мишу в бік жолоба. У цей момент на екрані з'являється "лампочка". (Спробуйте це кілька разів, якщо це не працює, як було призначено в перший раз). Потім ви можете натиснути на опцію поля створення, щоб створити uid. Сподіваюся, це допомагає людям, які зациклюються на цьому.
Ніяз

173

Встановіть плагін GenerateSerialVersionUID від Olivier Descout.

Перейдіть до: меню ФайлНалаштуванняПлагіниОгляд сховищGenerateSerialVersionUID

Встановіть плагін і перезапустіть.

Тепер ви можете створити ідентифікатор з меню КодСтворити → serialVersionUID` або ярлика.


14
Чи потрібно справді потрібен зовнішній плагін для того, щоб це працювало?
H.Rabiee

Так, вам потрібен плагін, який вже є частиною сховища плагінів IntelliJ.
Sileria

Працював для мене в Intellij IDEA 12.1
Sagar Hatekar

Для мене працює 13.0.2.
user1978019

Працює на Android Studio 0.8.9
Itai Hanski

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. Це німа "особливість", яка випливає із загального нерозуміння того, як цей ID використовує Java. Ви повинні давати цим ідентифікованим значущим, читабельним значенням, наприклад, починаючи з 1L та збільшуючи їх щоразу, коли ви думаєте, що нова версія класу повинна зробити всі попередні версії (які раніше можуть бути серіалізовані) застарілими. Усі утиліти, які генерують такі ідентифікатори, в основному роблять те, що робить JVM, коли ідентифікатор не визначений: вони генерують значення на основі вмісту файлу класу, отже, виходять з нечитабельними безглуздими довгими цілими числами. Якщо ви хочете, щоб кожна версія вашого класу була чіткою (в очах JVM), тоді вам навіть не слід вказувати значення serialVersionUID, тому JVM видасть його на льоту, і значення кожної версії вашого класу буде унікальною. Метою чіткого визначення цього значення є вказівка ​​механізму серіалізації для обробки різних версій класу, які мають однаковий SVUID, як ніби вони однакові, наприклад, не відхиляти старі серіалізовані версії. Отже, якщо ви визначаєте ідентифікатор і ніколи не змінюєте його (і я вважаю, що це ви робите, оскільки ви покладаєтесь на автогенерацію, і ви, ймовірно, ніколи не повторно генеруєте свої ідентифікатори), ви гарантуєте, що всі - навіть абсолютно різні - версії ваш клас буде вважатися таким же механізмом серіалізації. Це те, чого ти хочеш? Якщо ні, і якщо ви дійсно хочете мати контроль над тим, як ваші об’єкти розпізнаються, вам слід використовувати прості значення, які ви самі можете зрозуміти та легко оновити, коли вирішите, що клас суттєво змінився.

Сподіваюсь, це допомагає. Удачі.


2
Дякую, я так довго пропускав цей простий факт!
дедек

1
Я фактично повторно генерував serialVersionUIDби нове випадкове число, коли я не хочу підтримувати старі версії щодо десеріалізації. Можливо, мені не потрібно використовувати випадкові числа, але можна починати з 1 і збільшувати його. Однак 3Lдля мене тоді більше значення не має -3518231192373568183L. Тому, я думаю, обидва рішення працюють однаково. Випадкове число може мати ту перевагу, що воно пробуджує нелінійні історії з вилами та гілками.
JojOatXGME

16

Для того, щоб генерувати значення, використовуйте

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

і надайте змінній шаблону randomLong наступне значення: groovyScript ("новий Random (). nextLong (). abs ()")

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


1
люблю цей коментар, використовуючи шаблони в реальному часі, це, безумовно, найшвидше рішення та найбільш настроюється (я видалив новий рядок, наприклад). Для налаштування перейдіть до Android Studio> Налаштування> Редактор> Шаблони в реальному часі та створіть там новий (плюс значок) із цим значенням та використовуйте змінні змінення для введення сценарію
hcpl

13

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

Для цього натисніть Ctrl+Alt+S-> "Live Templates"розділ -> other(або без бажань)

А потім створіть нове з таким визначенням:

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

Потім виберіть definitionобласть і збережіть його як'serial'

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


3

Іншим способом генерування serialVersionUID є використання >Analyze >Run Inspection by Nameз контекстного меню (або скорочення клавіатури, яке за замовчуванням ctrl+ alt+ shift+ i), а потім введіть "Serializable class без 'serialVersionUID'" (або просто введіть "serialVersionUID" та тип попереду функція знайде це для вас.

Ідея> Аналіз> Запустити перевірку за назвою Потім ви отримаєте контекстне меню, де ви зможете вибрати, де слід проводити перевірки (наприклад, все з конкретного модуля, цілого проекту, одного файлу, ...)

При такому підході вам навіть не потрібно встановлювати загальні правила перевірки.


Приємно, це зробило роботу для мене. Він знайшов відсутню змінну і запропонував можливість її додати.
arenaq

@arenaq рада, що це допомогло комусь іншому ;-)
Олександр

2

З версією v2018.2.1

Йти до

Налаштування> Редактор> Інспекції> Java> Проблеми серіалізації> перемикання "Клас серіалізації без 'serialVersionUID'".

Поруч із декларацією класу повинно з’явитися попередження.


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, і вона заповнить цей простір випадково довгим.


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, зберігаючи сумісність зі старими класами.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.