Pracuję ze starszą aplikacją Java, która została napisana dla Javy 1.4, zanim pojawiły się Generics. Od tego czasu zakończyliśmy aktualizację do wersji Java 6.

Zastanawiamy się teraz nad wprowadzeniem zmiany w celu obsługi Generics w naszych kolekcjach, aby zapewnić kontrolę bezpieczeństwa typów w czasie kompilacji i zachować zdrowy rozsądek dla programistów.

Czy są jakieś zastrzeżenia lub problemy, o których powinniśmy wiedzieć, przeprowadzając to uaktualnienie?

5
Mark F Guerra 14 czerwiec 2011, 17:37
Zobacz Generyki w języku programowania Java. Zwłaszcza paragraf 10 „Konwertowanie starszego kodu na używanie generyków”.
 – 
MockerTim
14 czerwiec 2011, 17:44
Porady zawarte w tym dokumencie są z pewnością warte przeczytania: jest kilka prawdziwych problemów, zwłaszcza jeśli tworzysz API z innymi użytkownikami, a nie samodzielną aplikację.
 – 
Ben
14 czerwiec 2011, 18:00
Dziękuję. Mam szczęście, że mój kod jest przeznaczony do samodzielnej aplikacji, a nie do interfejsu API. Inni mogą nie mieć tyle szczęścia.
 – 
Mark F Guerra
14 czerwiec 2011, 23:16

3 odpowiedzi

Najlepsza odpowiedź
  1. Dowiedz się, jak działają generyki Java i ich ograniczenia.
  2. Użyj IDE z dobrą obsługą refaktoryzacji.
  3. Zrób to powoli i ostrożnie.
  4. Najpierw rób proste rzeczy i nie przeskakuj do tworzenia skomplikowanych klas ogólnych itp., dopóki nie wiesz, że są naprawdę potrzebne.
  5. Oprzyj się pokusie dodania @SuppressWarning("unchecked"), aby ostrzeżenia zniknęły.

Nie ma tu nic szczególnie głębokiego...

6
Etienne de Martel 14 czerwiec 2011, 18:37
+1: Adnotacja, której nie musisz używać, to @SuppressWarning("unchecked") Uwaga: Nawet kolekcje JDK kompilują się z tymi ostrzeżeniami. :(
 – 
Peter Lawrey
14 czerwiec 2011, 17:47
- tak, w niektórych przypadkach adnotacja jest nieunikniona. Ale przesłanie jest takie, że powinno być używane w ostateczności.
 – 
Stephen C
14 czerwiec 2011, 18:10
„niezaznaczone” musi być ciągiem pisanym małymi literami. Myślę, że większość ludzi unika używania, nie wiedząc, że tam jest. ;)
 – 
Peter Lawrey
14 czerwiec 2011, 18:31
Czy możesz podać przykład, w którym nie można było uniknąć niesprawdzonego ostrzeżenia, używając i rzutowania? Chyba nigdy tego nie widziałem
 – 
AmaDaden
14 czerwiec 2011, 19:18
C, jestem człowiekiem, który ma różne ostrzeżenia dla kompilatora, które niekonsekwentnie ignoruję. ;)
 – 
Peter Lawrey
14 czerwiec 2011, 19:45

Najważniejszą częścią aktualizacji, IMHO, jest upewnienie się, że programiści pracujący nad nią mają solidną wiedzę na temat generyków, szczególnie w odniesieniu do przekazywania kolekcji do funkcji i zwracania ich z funkcji, takich jak List<Animal> <> List<Tiger> itp. Zawsze powinieneś być w stanie wstawić generyki, nawet jeśli używasz generycznego Object lub ? symbole zastępcze.

Inną rzeczą, która sprawi, że konwersja będzie płynna/niezależna od kodu, jest to, że masz kolekcje zawierające jeden typ, że nie ma obiektów mieszanych, które wymuszają ? lub Obiekt „catch-all”. Może to być dość powszechne, zwłaszcza w przypadku Map.

Jeśli używasz jakichkolwiek podstawowych bibliotek, Hibernate, itp., możesz napotkać tam ograniczenia, jeśli podstawowa biblioteka nie obsługuje generyków. W takim przypadku będziesz musiał przeciekać kod biblioteki lub zawinąć obiekty (niezalecane).

Zmień części, które mają sens, zostaw części, które nie mają sensu, i rób to etapami, aby zawsze móc cofnąć kawałek, jeśli napotkasz problem.

1
Steven Mastandrea 14 czerwiec 2011, 17:45

Stephen jest martwy, ale dodałbym kilka wskazówek.

1) Ponieważ Generics to tylko czas kompilacji, są one bezużyteczne w kilku miejscach, takich jak odbicie i przechowywanie obiektów w sesji (jeśli jest to projekt sieciowy). Nie znam żadnego czystego sposobu radzenia sobie z tym. Polecam po prostu zadeklarować wszystko, co z tego wyniknie, jako <?> i po prostu zajmować się sprawdzaniem typu.

2) To ten, który spalił mnie w przeszłości. W definicjach metod użyj List<? extends Shape>, a nie List<Shape>. Jeśli masz typ Circle, który jest dzieckiem Shape, List<Circle> nie może zostać przekazany do List<Shape>, ale może zostać przekazany do List<? extends Shape> . Wydaje się to niewielkie, ale dla mnie pojawiło się bardzo nagle i wymagało wielu dodatkowych zmian w zajęciach, które myślałem, że zostały wykonane.

3) Nie sądzę, abyś NIGDY nie musiał tłumić ostrzeżeń o rodzajach, ponieważ zawsze możesz zmienić List na List<?> i się ich pozbyć. Jednak zalecam, abyś tego nie robił, chyba że ta część kodu nie może używać generyków (zobacz mój pierwszy punkt). Lepiej mieć ostrzeżenia, które planujesz naprawić, niż złe poprawki, które planujesz poprawić, ponieważ prawdopodobnie nigdy ich nie poprawisz, a ostrzeżenia będą rzucać ci się w twarz za każdym razem, gdy spojrzysz na swój projekt.

1
AmaDaden 14 czerwiec 2011, 18:28