Typowane struktury danych

Artykuły „Struktury danych” oraz „Zbiory” pozwoliły nam zapoznać się z podstawami programowania z wykorzystaniem kolekcji z biblioteki standardowej. Przedstawiony w nich styl programowania był perfekcyjnie poprawny… aż do czasu pojawienia się Javy w wersji 1.5. Począwszy od Javy w wersji 1.5 wszystkie struktury danych w bibliotece Java SE są typowane, co oznacza, że deklarując i tworząc obiekt kolekcji czy mapy musimy określić, jakiego typu elementy w tychże strukturach danych będziemy przechowywali. Przykładowo, pisząc:

Set mySet = new HashSet();

mówimy, że potrzebny jest nam zbiór, oraz tworzymy ten zbiór. Zauważmy, że nie ma tu nigdzie wskazania typu obiektów które będziemy chcieli w tym zbiorze przechowywać. Kod ten kompiluje się także w Javie w wersji 1.5 i nowszych, ale jeśli używamy tych nowych wersji to powinniśmy raczej napisać:

Set<Integer> mySet = new HashSet<Integer>();

Zauważmy, że powyższa linijka kodu jest bardzo podobna to tej poprzedniej, a jedyna różnica to typ Integer ujęty w nawiasy < > umieszczony tuż za typem kolekcji. W ten właśnie sposób określamy, że referencja mySet jest referencją wskazującą na zbiór przechowujący elementy typu Integer a nie po prostu na zbiór, oraz, że tworzymy i przypisujemy do tej zmiennej zbiór elementów typu Integer, a nie zbiór przechowujący elementy typu nieznanego.

Jeśli pokusiliśmy się o wykonanie zadania „Zbiory, zad. 1” dołączonego do artykułu „Zbiory” albo chociażby o uruchomienie podanego rozwiązania to zauważyliśmy, że kompilator zgłasza ostrzeżenia o użyciu zbioru bez podania typu jego elementów (jeśli używamy Javy 1.5 lub nowszej). Rozwiązanie tego problemu jest treścią kolejnego zadania, zadania „Zbiory, zad. 2”. Zachęcam do próby rozwiązania i do komentowania na forum!

Zerknijmy teraz do oficjalnej dokumentacji interfejsu java.util.Set. Jeśli otworzymy dokumentację do wersji 1.4.2 to nie zauważymy nic nadzwyczajnego, tj. będą tam wymienione metody zdefiniowane w tym interfejsie – cztery z nich już znamy, zapoznanie się z kolejnymi pozostawiam jako ćwiczenie dla chętnych. Jeśli jednak otworzymy dokumentację do wersji 1.5, to zauważymy, że nie ma już interfejsu java.util.Set, jest za to interfejs java.util.Set<E>. Nie ma też metody add(Object o), jest za to metoda add(E o). Oczywiście jest to ten sam interfejs i ta sama metoda, tyle że z uwzględnieniem typu elementów zbioru.

Deklarację java.util.Set<E> należy odczytywać tak, że jest to interfejs java.util.Set parametryzowany typem, i ten typ jest oznaczony literką E. Literka to nie jest w tym kontekście nazwa jakieś konkretnej klasy, tylko właśnie wskazanie, że w tym miejscu należy podać nazwę jakiejś klasy, gdy będziemy deklarowali referencje typu Set<E>.

Deklaracja add(E o) w odróżnieniu od deklaracji add(Object o) oznacza, że jest to metoda którą możemy wywołać przekazując argument tego samego typu, który określiliśmy deklarując zmienną typu Set<E> a nie argument typu Object. Jeśli więc napisalibyśmy:

Set<Integer> mySet = new HashSet<Integer>();

to nie moglibyśmy potem napisać:

mySet.add("Ola");

bo parametr „Ola” jest typu String a nie typu Integer, moglibyśmy za to jak najbardziej napisać:

mySet.add(1);

Literka użyta w definicji typu Set<E> i metody add(E o) sama w sobie nic nie oznacza, tj. mogłaby to być dowolna inna literka czy wieloliterowa nazwa. Ważne jest to, że zarówno w definicji typu Set<E> jak i w definicji metody add(E o) jest to ta sama litera, co oznacza, że jakikolwiek typ określimy tworząc referencję typu Set<E> to ten sam typ będzie użyty jako typ argumentu metody add(E o).

Jeśli teraz przejrzymy dokumentację dla Javy w wersji 1.5 dla klas HashSetczy TreeSet to zauważymy, że dokładnie tak jak w przypadku interfejsu Set<E> mamy deklaracje postaci HashSet<E> i TreeSet<E>. Znaczenie jest oczywiście takie samo jak dla interfejsu Set<E>, tj. są to te same klasy, tyle że parametryzowane typem przechowywanych przez siebie elementów.

0 0 votes
Daj ocenę