IntelliJ IDEA generuje serialVersionUID

297

Jak wygenerować tę wartość w IntelliJ IDEA?

Idę do Ustawienia -> Błędy -> Problemy z serializacją -> Klasa możliwa do serializacji bez „serialVersionUID”, ale nadal nie wyświetla mi ostrzeżenia. Mój rodzic PKladrBuilding rodzic implementuje interfejs Serializable .

Część kodu:

public class PKladrBuilding extends PRQObject

public abstract class PRQObject extends PObject

public abstract class PObject implements Serializable
Kirill Bazarov
źródło
3
Czy na pewno musisz wygenerować wartość zamiast definiować własną? Jeśli tworzysz nową klasę, zaleciłbym zdefiniowanie np. 1LJako swojego identyfikatora i przyrostu, gdy zmieni się formularz zserializowany. (Zobacz stackoverflow.com/questions/888335/… ).
Duncan Jones
1
stackoverflow.com/questions/24573643/... ma bardzo dobre rozwiązanie.
Pankaj Kumar

Odpowiedzi:

588

Nie jestem pewien, czy masz starą wersję IntelliJ IDEA, ale jeśli przejdę do menu PlikUstawienia ...InspekcjeProblemy z serializacją → Klasa możliwa do serializacji bez włączonej opcji „serialVersionUID”, klasa, którą podajesz, daje mi ostrzeżenia.

Wpisz opis zdjęcia tutaj

Jeśli spróbuję pierwszej klasy, zobaczę:

Wpisz opis zdjęcia tutaj

BTW: Nie pokazało mi ostrzeżenia, dopóki nie dodałem { }na końcu każdej klasy, aby naprawić błąd kompilacji.

Peter Lawrey
źródło
2
Spróbuj File| Invalidate Caches, jeśli to nie pomoże, skontaktuj się z [email protected] z przykładowym projektem do odtworzenia.
CrazyCoder,
1
Sprawdź idea.log(Pomoc | Reveal Log in ...) wyjątki, wiadomo, że zaszyfrowany katalog domowy w systemie Linux powoduje problemy z powodu błędu jądra .
CrazyCoder,
1
Mam tam wiele wyjątków .. jak java.lang.NoClassDefFoundError: org / intellij / lang / annotations / MagicConstant;
Kirill Bazarov
2
Ponownie zainstalowałem IDEA i usunąłem wtyczki i to mi pomaga. Wielkie dzięki.
Kirill Bazarov
5
Sposób, w jaki działałem w wersji 15, to najechanie kursorem na nazwę klasy, aby zobaczyć ostrzeżenie i powoli przesunąć mysz w kierunku rynny. W tym momencie na ekranie pojawia się „żarówka”. (Spróbuj to kilka razy, jeśli za pierwszym razem nie działa zgodnie z przeznaczeniem). Następnie możesz kliknąć opcję tworzenia pola, aby utworzyć identyfikator użytkownika. Mam nadzieję, że to pomaga ludziom, którzy utknęli w tym.
Niyaz
173

Zainstaluj wtyczkę GenerateSerialVersionUID autorstwa Oliviera Descouta.

Przejdź do: menu PlikUstawieniaWtyczkiPrzeglądaj repozytoriaGenerateSerialVersionUID

Zainstaluj wtyczkę i uruchom ponownie.

Teraz możesz wygenerować identyfikator z menu KodGeneruj → serialVersionUID` lub skrót.

Sileria
źródło
14
Czy naprawdę potrzebna jest zewnętrzna wtyczka, aby to działało?
H.Rabiee
Tak, potrzebujesz wtyczki, która jest już częścią repozytorium wtyczek IntelliJ.
Sileria
Pracowałem dla mnie nad Intellij IDEA 12.1
Sagar Hatekar
Działa dla mnie w 13.0.2.
user1978019
Działa na Androidzie Studio 0.8.9
Itai Hanski
67

Bez żadnych wtyczek: wystarczy włączyć wyróżnienie w IntelliJ:

IntelliJ Preferences -> Editor -> Inspections -> Java -> Serialization issues -> Serializable class without 'serialVersionUID'- ustaw flagę i kliknij 'OK'.

Teraz, jeśli twoja klasa zaimplementuje Serializable, zobaczysz wyróżnienie, a alt+Enterna nazwie klasy zaproponuje wygenerowanie private static final long serialVersionUID.

PS: Zaczerpnięte stąd

Nikhil Katre
źródło
4
Dzięki. Nie wiem, dlaczego nie widzę żarówki, ale kliknięcie nazwy klasy i wpisanie Alt-Enter rozwiązuje problem.
John S,
2
Odpowiedź została skradziona stąd
Serhii Maksymchuk
to jest bardziej aktualne
Christian Matthew
39

Po spędzeniu czasu na serializacji uważam, że nie powinniśmy generować serialVersionUID losowych wartości, powinniśmy nadać im znaczącą wartość.

Oto komentarz do szczegółów na ten temat. Skopiuję komentarz tutaj.

W rzeczywistości nie powinieneś „generować” identyfikatorów UID w wersji szeregowej. Jest to głupia „funkcja”, która wynika z ogólnego niezrozumienia sposobu używania tego identyfikatora przez Javę. Powinieneś nadać tym identyfikatorom znaczące, czytelne wartości, np. Zaczynając od 1L, i zwiększać je za każdym razem, gdy myślisz, że nowa wersja klasy powinna sprawić, że wszystkie poprzednie wersje (które mogły być wcześniej serializowane) stały się nieaktualne. Wszystkie narzędzia, które generują takie identyfikatory, w zasadzie robią to, co robi JVM, gdy identyfikator nie jest zdefiniowany: generują wartość na podstawie zawartości pliku klasy, stąd powstają nieczytelne długie liczby całkowite bez znaczenia. Jeśli chcesz, aby każda wersja twojej klasy była odrębna (w oczach JVM), nie powinieneś nawet określać wartości serialVersionUID, ponieważ JVM będzie produkować ją w locie, a wartość każdej wersji twojej klasy będzie niepowtarzalna. Celem jawnego zdefiniowania tej wartości jest poinformowanie mechanizmu serializacji, aby traktował różne wersje klasy, które mają ten sam SVUID, jakby były takie same, np. Aby nie odrzucał starszych wersji serializowanych. Jeśli więc zdefiniujesz identyfikator i nigdy go nie zmienisz (i zakładam, że tak właśnie postępujesz, ponieważ polegasz na automatycznym generowaniu i prawdopodobnie nigdy nie generujesz ponownie swoich identyfikatorów), zapewniasz, że wszystkie - nawet absolutnie różne - wersje twoja klasa będzie traktowana tak samo przez mechanizm serializacji. Czy tego chcesz? Jeśli nie, i jeśli naprawdę chcesz mieć kontrolę nad sposobem rozpoznawania obiektów, powinieneś używać prostych wartości, które sam możesz zrozumieć i łatwo zaktualizować, gdy zdecydujesz, że klasa znacząco się zmieniła.

Mam nadzieję że to pomoże. Powodzenia.

Emdadul Sawon
źródło
2
Dzięki, tak długo pomijałem ten prosty fakt!
dedek,
1
Naprawdę wygenerowałbym ponownie serialVersionUIDz nową losową liczbą, gdy nie chcę obsługiwać starych wersji przy deserializacji. Może nie muszę używać liczb losowych, ale mogę zacząć od 1 i zwiększyć go. Nie 3Lma to jednak dla mnie większego znaczenia -3518231192373568183L. Dlatego wydaje mi się, że oba rozwiązania działają podobnie. Jednak liczba losowa może mieć tę zaletę, że budzi się w nieliniowych historiach z widelcami i rozgałęzieniami.
JojOatXGME
16

Aby wygenerować wartość, użyj

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

i podaj zmienną szablonu randomLong o następującej wartości: groovyScript („new Random (). nextLong (). abs ()”)

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

pharsfalvi
źródło
1
uwielbiam ten komentarz, używając szablonów na żywo jest to z pewnością najszybsze rozwiązanie i najbardziej konfigurowalne (na przykład usunąłem nowy wiersz). Aby skonfigurować, przejdź do Android Studio> Preferencje> Edytor> Szablony na żywo i utwórz tam nową (z ikoną) o tej wartości i użyj zmiennych edycji, aby wprowadzić skrypt
hcpl
13

Ponadto możesz dodać szablon na żywo, który wykona pracę.

Aby to zrobić, naciśnij Ctrl+Alt+S-> "Live Templates"sekcja -> other(lub w / e chcesz)

A następnie utwórz nową z taką definicją:

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

Następnie wybierz definitionzakres i zapisz go jako'serial'

Teraz możesz wpisać serialTABtreść klasy.

fallens4e
źródło
3

Innym sposobem na wygenerowanie serialVersionUID jest użycie >Analyze >Run Inspection by Namez menu kontekstowego (lub skrótu klawiaturowego, który domyślnie jest ctrl+ alt+ shift+ i), a następnie wpisz „Serializable class bez„ serialVersionUID ”” (lub po prostu wpisz „serialVersionUID” i typ naprzód funkcja znajdzie to dla ciebie.

Pomysł> Analiza> Uruchom inspekcję według nazwy Otrzymasz wtedy menu kontekstowe, w którym możesz wybrać, gdzie przeprowadzać inspekcje (np. Wszystkie z określonego modułu, całego projektu, jednego pliku, ...)

Dzięki takiemu podejściu nie musisz nawet ustawiać ogólnych zasad inspekcji na niczym.

Alexander
źródło
Fajnie, to zadziałało dla mnie. Znalazł brakującą zmienną i przedstawił opcję jej dodania.
arenaq
@arenaq cieszę się, że pomogło to komuś innemu ;-)
Alexander
2

Z wersją v2018.2.1

Iść do

Preferencje> Edytor> Inspekcje> Java> Problemy z serializacją> przełącz „Serializowalną klasę bez„ serialVersionUID ””.

Ostrzeżenie powinno pojawić się obok deklaracji klasy.

YLyu
źródło
1

Korzystam z Androida Studio 2.1 i mam większą spójność w uzyskiwaniu żarówki, klikając nazwę klasy i najeżdżając na nią myszą przez sekundę.

Johnny Wu
źródło
1

Dodaj szablon aktywny o nazwie „ser” do drugiej grupy, ustaw go na „Dotyczy w Javie: deklaracja” i odznacz „Skróć nazwy FQ”. Daj mu tekst szablonu:

$serial$

Teraz edytuj zmienne i ustaw serial na:

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())

Zakłada standardowy układ projektu Gradle. Zmień / build / to / target / for Maven.

Greg Allen
źródło
1

Najłatwiejsza nowoczesna metoda: Alt+ Enterwłączony

private static final long serialVersionUID = ;

IntelliJ podkreśli przestrzeń po =. umieść na nim kursor i naciśnij alt+ Enter( Option+ Enterna Macu). Pojawi się okienko z napisem „Losowo zmień inicjator serialVersionUID”. Po prostu wciśnij Enter, a zapełni to miejsce losową długością.

jeremysprofile
źródło
0

Jeśli chcesz dodać nieobecny serialVersionUID dla kilku plików, IntelliJ IDEA może nie działać zbyt dobrze. Wymyślam prosty skrypt, aby z łatwością osiągnąć ten cel:

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

Zapisujesz ten skrypt, powiedz jak add_serialVersionUID.shw ~/binfolderze. Następnie uruchom go w katalogu głównym projektu Maven lub Gradle, np .:

add_serialVersionUID.sh < myJavaToAmend.lst

Ten plik .lst zawiera listę plików Java do dodania serialVersionUID w następującym formacie:

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

Ten skrypt używa narzędzia JDK serialVer. Jest to idealne rozwiązanie w sytuacji, gdy chcesz zmienić ogromną liczbę klas, które w pierwszej kolejności nie miały ustawionego serialVersionUID, zachowując zgodność ze starymi klasami.

schnell18
źródło