2015-12-29 16 views
9

Załóżmy, że mam dwie klasy A i B, która rozszerza A. Z następującym sposobem mogę wydrukować Collection z A czy coś rozszerzenie A:Czy <? rozszerza ...> wyłączność parametrów metody?

private static void print(Collection<? extends A> collection) { 

    for (A element : collection) { 
     System.out.println(element); 
    } 

} 

To wspaniałe, mogę zrobić coś takiego:

public static void main(String[] args) { 

    List<A> l1 = new ArrayList<>(); 
    l1.add(new A()); 
    l1.add(new B()); 
    print(l1); 

    List<B> l2 = new ArrayList<>(); 
    l2.add(new B()); 
    l2.add(new B()); 
    print(l2); 

} 

Teraz moje pytanie brzmi: dlaczego w moim sposobie main (lub gdzie indziej) mogę napisać ten

List<? extends A> l3 = new ArrayList<>(); 

ale nie ten

l3.add(new A()); 
l3.add(new B()); 

Rozumiem, dlaczego nie mogę dodać wystąpienia A lub B w l3. Ale dlaczego pierwsze stwierdzenie, które wydaje się bezużyteczne, jest autoryzowane?

EDIT

Pytam z innymi słowami, ponieważ myślę, że moje pytanie jest źle.

Co mogę zrobić z pustą listą List<? extends A> l3 = new ArrayList<>();? Wiem, że nie można nic dodać, ponieważ typ listy jest nieznany.

Odpowiedz

-1

Odpowiedź brzmi: GENERICS, Typy A i B są znane dopiero po uruchomieniu. Więc Java nie może ich utworzyć.

Więcej proszę czytać Oracle Generics Documentation

6

List<? extends A> l3 oznacza, że ​​l3może być się List<A> albo może byćList<B>. <? extends A> oznacza, że ​​kompilator nie wie i nie może bezpiecznie założyć więcej.

Ponieważ to może byćList<B>, l3.add(new A()) nie jest bezpieczne. ? „Rozciąga się” Lista byłby uszkodzony, ponieważ nie byłoby naprawdę zawierają tylko przypadki B.

+2

to może być nawet 'Lista ', gdzie 'C' jest kolejnym cl tyłek przedłużający "A". Więc również 'add (new B())' nie jest bezpieczny. – Henry

+0

Więc nie ma sensu pisać 'List l3 = nowa ArrayList <>();' ponieważ nie można jej później użyć? – cheb1k4

+0

Jest użyteczny. Po prostu nie możesz do tego dodać. – VGR

0

Leki generyczne nie są kowariantna i nie jest A. Tak więc nie można zrobić:

List<? extends A> l = new ArrayList<>(); 
l.add(new A()); 

z tych samych powodów nie można zrobić:

List<B> l = new ArrayList<>(); 
l.add(new A()); 

ani też:

List<String> l = new ArrayList<>(); 
l.add(new Object()); 
+0

Wiem, że nie mogę tego zrobić.Moje pytanie brzmi: dlaczego mogę napisać 'List l3 = new ArrayList <>();' podczas gdy to, o czym wspomniałeś, jest niedozwolone. – cheb1k4

Powiązane problemy