<和有什么区别?扩展了Foo>和<Foo>


20

我似乎对<Foo>和之间的区别有误解<? extends Foo>。据我了解,如果我们有

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

这表明Foo可以将类型的对象添加到此数组列表中。由于的子类Foo也是type Foo,因此也可以添加它们而不会出现错误,如下所示

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

在哪里Bar extends Foo

现在,说我定义foos

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

我目前的理解是,这表示some unknown type that extends Foo。我的意思是可以将任何属于其子类的对象Foo添加到此列表中。表示ArrayList<Foo>和之间没有区别ArrayList<? extends Foo>

为了对此进行测试,我尝试编写以下代码

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

但系统提示以下编译错误

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)

根据目前的理解,我可以理解为什么为什么我不能在Foo的列表中添加<? extends Foo>,因为它不是其自身的子类。但是我很好奇为什么我不能Bar在列表中添加一个。

我的理解力在哪里?



1
<? extends Foo>是一个特定的未知的扩展类Foo。此类的操作只有在的任何子类都合法的情况下才是合法的Foo
2015年

3
哇。您对Java的泛型了解得越多,发现的内容就越复杂。
梅森·惠勒

Answers:


15

正如您自己发现的那样,ArrayList声明为as ArrayList<? extends Foo> subFoos = new ArrayList<>();不会很有用。

为了看到有用的<? extends T>考虑:

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

以后可以使用如下:

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

或如下:

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

请注意,如果collect方法声明如下,则以上方法均无效:

List<Foo> collect( List<Foo> a1, List<Foo> a2 )
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.