开发者

Generic collection & wildcard in java

I am having problems getting my head around generics in the following situation, see inline comments below for my questions:

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 p开发者_开发百科oint in using the wildcard in the first place?  
}


//Intuitively I would expect this to mean that test is set containing objects 
//that subclass AbstractGroup
Set<? extends AbstractGroup> test;

Nope, it means that it's a set of one specific ? which extends AbstractGroup. And neither you nor the Compiler have any way of knowing what that ? is, so there's no way you can add anything to that Set.

You can assign the set's values to variables of type AbstractGroup, but not the other way around.

Instead, you need this:

Set<? super AbstractGroup> test;

This principle is sometimes called PECS and explained well in this answer.


Set<? extends AbstractGroup> test;

This means your set can be a set of any object that extends AbstractGroup, but normally the compiler would not allow you to add something to that set (since it can't tell whether you'd for example add a SubGroupB to a Set<SubGroupA> etc.).

test = new HashSet<SubGroupA>()

Your actual set would only contain objects of type SubGroupA and subclasses thereof. However, the compiler would still not know what the content of test would be (see above).

The point of the wild card is: you can assign any set to the variable that is parameterized with AbstractGroup or a subclass, thus assuring you can cast all objects already in that map to AbstractGroup (which the compiler checks for).

If you want to have a set that can contain any AbstractGroup object, just don't use the wildcard.

//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());


You don't need wildcards here In your case it would suffice to say

Set<AbstractGroup> test;

And you can then put any subclass of AbstractGroup into the set.

Also, it doesn't look like you're initializing test in your code above.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜