【问题标题】:Generic collection & wildcard in javajava中的通用集合和通配符
【发布时间】:2011-11-13 20:36:15
【问题描述】:
在以下情况下,我无法理解泛型,请参阅下面的内联 cmets 了解我的问题:
public void exampleMethod() {
//Intuitively I would expect this to mean that test is set containing objects
//that subclass AbstractGroup
Set<? extends AbstractGroup> test;
//Yet the compiler complains here and I do not understand why?
test.add(new AnyAbstractGroupSubGroup());
//I would guess that a method call such as this at runtime
test = new HashSet<SubGroupA>()
//would mean that only objects of subgroupA can be added to the collection, but then
//what is the point in using the wildcard in the first place?
}
【问题讨论】:
标签:
java
generics
collections
wildcard
【解决方案1】:
//Intuitively I would expect this to mean that test is set containing objects
//that subclass AbstractGroup
Set<? extends AbstractGroup> test;
不,这意味着它是一组特定的?它扩展了 AbstractGroup。你和编译器都不知道那是什么?是的,所以您无法向该 Set 添加任何内容。
您可以将集合的值分配给 AbstractGroup 类型的变量,但反之则不行。
相反,你需要这个:
Set<? super AbstractGroup> test;
这个原则有时被称为PECS,解释得很好in this answer。
【解决方案2】:
Set<? extends AbstractGroup> test;
这意味着您的集合可以是扩展AbstractGroup 的任何对象的集合,但通常编译器不允许您向该集合添加某些内容(因为它无法判断您是否会添加一个 @ 987654323@ 到 Set<SubGroupA> 等)。
test = new HashSet<SubGroupA>()
您的实际集合只包含SubGroupA 类型的对象及其子类。
但是,编译器仍然不知道test 的内容是什么(见上文)。
通配符的要点是:您可以将任何集合分配给使用AbstractGroup 或子类参数化的变量,从而确保您可以将映射到@ 的所有已经在中的对象强制转换987654329@(编译器检查)。
如果您想拥有一个可以包含任何 AbstractGroup 对象的集合,请不要使用通配符。
//this would compile (under the assumption that SubGroupA extends AbstractGroup)
Set<? extends AbstractGroup> test = new HashSet<SubGroupA>();
//this wouldn't compile, since the compiler doesn't know the type of test (it might change at runtime etc.)
test.add(new SubGroupA());
//this wouldn't compile since AbstractGroup and SubGroupA are not the exact same type (hence the wildcard would be needed here)
Set<AbstractGroup> test = new HashSet<SubGroupA>();
//this would compile
Set<AbstractGroup> test = new HashSet<AbstractGroup>();
test.add(new SubGroupA());
【解决方案3】:
这里不需要通配符在你的情况下,说
Set<AbstractGroup> test;
然后您可以将 AbstractGroup 的任何子类放入集合中。
此外,您似乎没有在上面的代码中初始化测试。