Jest to mały fragment kodu wzięty z niektórych przykładów towarzyszących parserowi Stanforda. Zajmuję się programowaniem w Javie od około 4 lat, ale nigdy nie bardzo dobrze rozumiałem, co powinien wskazywać ten styl kodu.
List<? extends HasWord> wordList = toke.tokenize();
Nie martwię się o szczegóły kodu. To, co mnie dezorientuje, to dokładnie to, co powinno przekazać ogólne wyrażenie w języku angielskim.
Czy ktoś może mi to wyjaśnić?
Odpowiedzi:
oznacza „klasę / interfejs, który się rozszerza
HasWord
”. Innymi słowy, onHasWord
sam lub którekolwiek z jego dzieci ... w zasadzie wszystko, co działałoby zinstanceof HasWord
plusemnull
.Mówiąc bardziej technicznie,
? extends HasWord
jest to symbol wieloznaczny ograniczony, objęty pozycją 31 Effective Java 3rd Edition , począwszy od strony 139. Ten sam rozdział z 2nd Edition jest dostępny online w formacie PDF ; część ograniczonych symboli wieloznacznych to pozycja 28, począwszy od strony 134.Aktualizacja: link PDF został zaktualizowany, ponieważ Oracle usunął go jakiś czas temu. Teraz wskazuje na kopię hostowaną przez School of Electronic Engineering and Computer Science na Queen Mary University of London.
Aktualizacja 2: Przejdźmy trochę bardziej szczegółowo do tego, dlaczego chcesz używać symboli wieloznacznych.
Jeśli zadeklarujesz metodę, której podpis spodziewasz się przekazać
List<HasWord>
, jedyną rzeczą, którą możesz przekazać, jestList<HasWord>
.Jeśli jednak wspomniany podpis
List<? extends HasWord>
byłby, możnaList<ChildOfHasWord>
zamiast tego przekazać .Zauważ, że istnieje subtelna różnica między
List<? extends HasWord>
iList<? super HasWord>
. Jak ujął to Joshua Bloch: PECS = producent rozszerza, konsument super.Oznacza to, że jeśli przekazujesz kolekcję, z której twoja metoda pobiera dane (tj. Kolekcja wytwarza elementy do użycia przez metodę), powinieneś jej użyć
extends
. Jeśli przekazujesz kolekcję, do której twoja metoda dodaje dane (tj. Kolekcja zużywa elementy tworzone przez twoją metodę), należy jej użyćsuper
.Może to brzmieć myląco. Jednak można go zobaczyć w
List
„ssort
polecenia (które jest po prostu skrót do wersji dwu-Arg z Collections.sort). Zamiast braćComparator<T>
, w rzeczywistości zajmujeComparator<? super T>
. W takim przypadku Komparator zużywa elementyList
, aby zmienić kolejność samej listy.źródło
List<HasWord>
jest dokładnie tym, co opisujesz: lista zawierająca dowolne obiekty,x
dla którychx instanceof HasWord
zwraca true, oraznull
. Nie potrzebujesz do tego znaku wieloznacznego. Symbol wieloznaczny oznacza, że tak naprawdę może to być również lista innego typu, o ile ten typ jest podtypemHasWord
. (Przepraszam za późny komentarz.)Znak zapytania oznacza „dowolny typ”.
?
sam oznaczapodczas gdy powyższy przykład oznacza
źródło
public Set<Class<?>> getClasses()
znaczy? Jaka jest różnicaSet<Class>
? Patrzę najavax.ws.rs.core.Application
.List<? extends HasWord>
akceptuje wszelkie konkretne klasy, które rozszerzają HasWord. Jeśli masz następujące klasy ......
wordList
może zawierać TYLKO listę As lub Bs lub ich kombinację, ponieważ obie klasy rozszerzają tego samego rodzica lubnull
(co nie sprawdza instancji sprawdzaniaHasWorld
).źródło
List<? extends Collection<String>> list = new ArrayList<List<String>>();
.List<HasWord>
równie dobrze. Chodzi o to, że ta zmienna może zawierać aList<A>
lubList<B>
aList<HasWord>
.Być może pomógłby wymyślony przykład „prawdziwego świata”.
W moim miejscu pracy mamy kosze na śmieci o różnych smakach. Wszystkie pojemniki zawierają śmieci, ale niektóre pojemniki są specjalistyczne i nie przyjmują wszystkich rodzajów śmieci. Więc mamy
Bin<CupRubbish>
iBin<RecylcableRubbish>
. System typów musi upewnić się, że nie mogę umieścić mojegoHalfEatenSandwichRubbish
w żadnym z tych typów, ale może przejść do ogólnego kosza na śmieciBin<Rubbish>
. Gdybym chciał porozmawiać o jednymBin
z tych,Rubbish
które mogą być wyspecjalizowane, więc nie mogę wrzucać niekompatybilnych śmieci, to byłoby to możliweBin<? extends Rubbish>
.(Uwaga:
? extends
nie oznacza tylko do odczytu. Na przykład mogę, przy zachowaniu odpowiednich środków ostrożności, wyjąć śmieci z kosza o nieznanej specjalizacji, a następnie umieścić je z powrotem w innym miejscu).Nie jestem pewien, jak bardzo to pomaga. Wskaźnik do wskaźnika w obecności polimorfizmu nie jest całkowicie oczywisty.
źródło
Po angielsku:
Ogólnie rzecz biorąc,
?
rodzajowe oznacza dowolną klasę. Iextends SomeClass
określa, że ten obiekt musi się rozszerzaćSomeClass
(lub być tą klasą).źródło
Znak zapytania służy do definiowania symboli wieloznacznych . Zapoznaj się z dokumentacją Oracle na ich temat: http://docs.oracle.com/javase/tutorial/java/generics/wildcards.html
źródło