2013-07-02 10 views
5

Zastanawiałem się, dlaczego następujący fragment kodu nie działa:Generics <? super> wieloznaczne

Collection <? super String> col = new ArrayList<String>(); 
col.add(new Object());// does not compile 
col.add("yo!");// compiles indeed; 

Jeśli typ jest <? super String> może zawierać niczego, co jest super od String (String w zestawie) nie?

+4

' 'może tylko dodać String. 'Obiekt' nie może być łańcuchem. Spróbuj:' Object myObj = new String(); 'i powinno działać. – Maroun

+1

Nie, wszystko, co ** rozszerza ** String. To znaczy *? którego super jest String *. – m0skit0

+0

@ m0skit0 to miejsce, w którym się pomyliłem. Dzięki. – Rollerball

Odpowiedz

15

Collection<? super String>, sprzeczne z intuicją, nie znaczy „zbiór, który zawiera obiekty typu String lub jego supertypem”. Oznacza to, że "col będzie zbiorem posiadającym określony rodzaj, który sam w sobie jest String lub jego nadtypem" (taki jak Object, Serializable lub CharSequence).

Najlepszym sposobem na myślenie o Collection<? super String> jest to, że nie jest to typ, jak przyzwyczaiłeś się w Javie, ale wzór , przeciwko któremu określone typy są dopasowane.

Teraz jedyną rzeczą, którą można bezpiecznie dodać do dowolnej kolekcji, która pasuje do powyższego wzoru, jest String lub jej podklasa (jeśli taka była). Wręcz przeciwnie do tego, czego byś się spodziewał, prawda? To Generics dla ciebie.

+0

Heh, nice. Aby uzupełnić twój przykład, 'String' może zostać umieszczony w' Collection '... –

+0

Dziękuję za jasne wyjaśnienie Marko, to nie pierwszy raz Twoja odpowiedź pomaga mi –

3

Z Collection <? super String>, nie wiemy, jakiego rodzaju obiektów zawiera dokładnie, ale wiemy, że to musi być zbiorem obu String lub niektóre nadklasą String, czyli jest to bezpieczne umieścićString w ale niekoniecznie musi to być Object. Odwrotnie, dla metod, które pobierają z kolekcji (np. Podczas iteracji), nie możemy być pewni, że otrzymamy ciągi z powrotem.

Z drugiej strony z Collection<? extends Foo> wiemy, że to zbiór czegoś, co jest albo Foo lub niektórych podklasą Foo, więc możemy bezpiecznie wziąć coś z kolekcji i wiem to będzie przypisane do Foo, ale możemy "t umieścić wszystko, ponieważ nie mamy sposobu, aby wiedzieć, jakie typy byłyby bezpieczne.

+0

Świetne wyjaśnienie, teraz rozumiem lepiej ~ – bean