Java泛型参数和继承

时间:2011-08-03 13:43:02

标签: java generics inheritance polymorphism

我们知道ViewGroup扩展了View。
此外,我们有一个通用的参数化class A<T extends View>

问题:
为什么方法C.add()不接受new A<ViewGroup>()作为参数?
由于多态性,它不应该起作用吗?

Class diagram

解: 使用? extends View加入歌唱,可以添加接受new A<ViewGroup>()作为参数。

Solution

4 个答案:

答案 0 :(得分:7)

您已将add方法签名为:

static void add(A<View>)

但你可能意味着:

static void add(A<? extends View> a)

答案 1 :(得分:1)

不完全是因为add()可能正在使用View中找不到的ViewGroup方法。

摘要:ViewViewGroup,但ViewGroup不是View。您可以在多态性中将View对象分配给ViewGroup声明。

答案 2 :(得分:1)

首先,您的问题不是很清楚,因为UML图与您的文本相矛盾。你说View扩展了ViewGroup,但是图表反过来了:ViewGroup扩展了View。

现在,List<Car>不会延伸List<Vehicle>。如果是这样的话,你可以这样做:

List<Car> listOfCars = new ArrayList<Car>();
List<Vehicle> listOfVehicles = listOfCars;
listOfVehicles.add(new Bicycle());
// now the list of cars contain a bicycle. Not pretty. 

答案 3 :(得分:1)

首先你说View扩展了ViewGroup,但是图表说ViewGroup扩展了View(我认为是正确的)。

其次,您不能将List<ViewGroup>作为List<View>传递。这是一个编译时保护,以防止有人将AnotherView添加到此列表中并损害泛型的类型安全性。

List<ViewGroup>不是List<View>的子类型,但它是List<? extends View>的子类型。因此,您可以修改方法以接受List<? extends View>,但请注意,您无法以这种方式添加到传递给方法的列表中。

还有另一种称为下界通配符(List<? super ViewGroup>)的语法,与上面提到的上限通配符相反,它允许您添加到列表但是您可以在ViewGroup列表中传递或者父母。

有关泛型中通配符的更多信息,请访问:http://download.oracle.com/javase/tutorial/java/generics/wildcards.html