2011-06-07 73 views
3

下面的代码对我来说完全有意义 - 关于添加一个类型为T和S的超类型的元素肯定是这样的一个超类型,那么为什么编译器拒绝将'元素'添加到集合中呢?无法编译的有界通用方法 - 为什么?

class GenericType<S,T extends S>{ 
    void add1(Collection<? super T> col ,S element){ 
     col.add(element); // error 
     // The method add(capture#9-of ? super T) in the type 
     // Collection<capture#9-of ? super T> is not applicable for the arguments (S) 
    } 
} 

回答

2

Collection<? super T>意味着“集合,可以包含T和它的任何超” - 它实际上不可能制定该限制。它的意思是“一个只能包含某个特定类的实例的集合,它是T的超类” - 基本上它确保您可以将T添加到集合中。

该方法可以调用Collection<T>,但是你想添加一个S它。

+0

给你说什么,怎么那么该声明从东西做*不*使用通配符(收藏而不是收集)有什么不同? – Bhaskar 2011-06-07 12:07:49

+0

@Bhaskar:通配符还允许您使用Collection 或Collection 来调用该方法 - 您可以添加T的所有内容。 – 2011-06-07 12:20:40

5

Thake一个例子,如果A <- B <- C其中<-指的是超类型,那么如果S = BT = C你不能的S一个实例添加到T集合。

超型T可能是另一种超型T(在这种情况下为S)的超型或亚型。

+0

是的我同意你的推导,但事实仍然是S是一个超类型 - 那么为什么这个事实不足以允许这个加法呢?我可以看到,如果允许,也会导致可能的运行时异常,那是因为设计人员决定避免进入这种运行时情况?如果你,那么收集和收集以上用法有什么区别? – Bhaskar 2011-06-07 12:11:31

+0

确实是正确的答案,但必须把它交给迈克尔让我用散文理解它。 – Bhaskar 2011-06-07 12:32:13

0

您正在尝试将类型S的元素放入类型T的集合中。泛型不是多态的。 你必须注意这里的两个问题。你想创造型的concreteObject扩展对象的集合,并添加对象 所以,当你有

Car extends Vehicle{} 
ElectricCar extends Car{} 

你正在尝试做的

Collection<? extends Car> collection; 
collection.add(new Vehicle()); 

第二个问题在于非多态性泛型的本质。看到这个伟大的解释 - >Is List<Dog> a subclass of List<Animal>? Why aren't Java's generics implicitly polymorphic?

2
new GenericType<Object,Integer>().add1(new ArrayList<Integer>(), ""); 
+0

对于有效的具体和不安全的示例,为+1。尽管如果你传入一个'ArrayList ',可能会更清楚你正在执行“超级”关键字。使用'ArrayList '确实显示了OP的推理中最明显的缺陷,因为'List '承认'List '显然不会接受任意超类型的'T'。 – 2011-06-07 12:23:04

+0

+1为简明和准确的代码带来的缺陷 – Bhaskar 2011-06-07 12:33:32

相关问题