Wydaje mi się, że mam nieporozumienie na temat różnicy między <Foo>
i <? extends Foo>
. Z mojego zrozumienia, gdybyśmy mieli
ArrayList<Foo> foos = new ArrayList<>();
Oznacza to, że Foo
do tej listy tablic można dodać obiekty typu . Ponieważ podklasy Foo
są również typu Foo
, można je również dodawać bezbłędnie, jak pokazano za pomocą
ArrayList<Foo> foos = new ArrayList<>();
foos.add(new Foo());
foos.add(new Bar());
gdzie Bar extends Foo
.
Powiedzmy, że zdefiniowałem foos
jako
ArrayList<? extends Foo> foos = new ArrayList<>();
Moje obecne rozumienie jest takie, że to wyraża some unknown type that extends Foo
. Rozumiem, że oznacza to, że wszelkie obiekty, które są podklasą, Foo
można dodać do tej listy; co oznacza, że nie ma różnicy między ArrayList<Foo>
i ArrayList<? extends Foo>
.
Aby to przetestować, próbowałem napisać następujący kod
ArrayList<? extends Foo> subFoos = new ArrayList<>();
subFoos.add(new Foo());
subFoos.add(new Bar());
ale został wyświetlony monit o następujący błąd kompilacji
no suitable method found for add(Foo)
method java.util.Collection.add(capture#1 of ? extends Foo) is not applicable
(argument mismatch; Foo cannot be converted to capture#1 of ? extends Foo)
no suitable method found for add(Bar)
method java.util.Collection.add(capture#2 of ? extends Bar) is not applicable
(argument mismatch; Bar cannot be converted to capture#2 of ? extends Bar)
W oparciu o moje obecne rozumienie rozumiem, dlaczego mogę nie być w stanie dodać Foo
listy do listy <? extends Foo>
, ponieważ nie jest ona sama w sobie podklasą; ale jestem ciekawy, dlaczego nie mogę dodać Bar
listy do listy.
Gdzie jest dziura w moim rozumieniu?
<? extends Foo>
jest specyficzną i nieznaną klasą, która się rozszerzaFoo
. Operacja z tą klasą jest legalna tylko wtedy, gdy byłaby legalna dla dowolnej podklasyFoo
.Odpowiedzi:
Jak sam odkryłeś,
ArrayList
deklaracja jakoArrayList<? extends Foo> subFoos = new ArrayList<>();
nie byłaby bardzo przydatna.Aby zobaczyć przydatność,
<? extends T>
zastanów się nad tym:które można później wykorzystać w następujący sposób:
lub w następujący sposób:
zwróć uwagę, że żadne z powyższych nie zadziałałoby, gdyby
collect
metoda została zadeklarowana w następujący sposób:źródło