<Arasındaki fark nedir? Foo> ve <Foo>


20

Ben arasındaki fark hakkında bir yanlış anlamayı var gibi <Foo>ve <? extends Foo>. Anladığım kadarıyla,

ArrayList<Foo> foos = new ArrayList<>();

Bu tür nesnelerin Foobu dizi listesine eklenebileceğini gösterir. Alt sınıfları Fooda tür Fooolduğundan, ile gösterildiği gibi hatasız olarak eklenebilirler

ArrayList<Foo> foos = new ArrayList<>();
foos.add(new Foo());
foos.add(new Bar());

nerede Bar extends Foo.

Şimdi, tanımlanmış olduğunu söylemek foosolarak

ArrayList<? extends Foo> foos = new ArrayList<>();

Şu anki anlayışım bunun ifade ettiği some unknown type that extends Foo. Bunu bir alt sınıf olan nesnelerin Foobu listeye eklenebileceği anlamına gelir ; yani ArrayList<Foo>ve arasında bir fark yoktur ArrayList<? extends Foo>.

Bunu test etmek için aşağıdaki kodu yazmaya çalıştım

ArrayList<? extends Foo> subFoos = new ArrayList<>();
subFoos.add(new Foo());
subFoos.add(new Bar());

ancak aşağıdaki derleme hatasıyla karşılaşıldı

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)

Mevcut anlayışım temelinde, neden Foobir listeye a ekleyemeyebileceğimi görebiliyorum <? extends Foo>, çünkü bu kendi başına bir alt sınıf değil; ancak neden Barlisteye a ekleyemediğimi merak ediyorum .

Anladığımdaki delik nerede?



1
<? extends Foo>Bir olan belirli ve bilinmeyen uzanır sınıf Foo. Bu sınıfla yapılan bir işlem, yalnızca herhangi bir alt sınıfı için yasal olacaksa yasaldır Foo.
Sıradan

3
Vay. Java'nın jeneriklerini ne kadar çok öğrenirseniz, o kadar çok berbatlık bulursunuz.
Mason Wheeler

Yanıtlar:


15

Kendi başınıza keşfettiğiniz ArrayListgibi , beyan etmek ArrayList<? extends Foo> subFoos = new ArrayList<>();çok yararlı olmaz.

Bunun yararını görmek için şunu <? extends T>göz önünde bulundurun:

List<Foo> collect( List<? extends Foo> a1, List<? extends Foo> a2 )
{
    List<Foo> collected = new ArrayList<>();
    collected.addAll( a1 );
    collected.addAll( a2 );
    return collected;
}

daha sonra aşağıdaki gibi kullanılabilir:

List<Foo> foos = collect( new ArrayList<Foo>(), new ArrayList<Bar>() );

veya aşağıdaki gibi:

List<Foo> foos = collect( new ArrayList<Bar>(), new ArrayList<Foo>() );

collectyöntem aşağıdaki gibi beyan edilmiş olsaydı, yukarıdakilerin hiçbirinin işe yaramayacağını unutmayın :

List<Foo> collect( List<Foo> a1, List<Foo> a2 )
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.