What is the difference between these two methods?
Collection<Type> getTypes();
vs
Collection<? extends Type> getTypes();
Does it matter if Type is a class or an interface? Especially, when designing an API, which version would be preferred and why?
Collection<Type> getTypes();
Here, getTypes()
must return a Collection<Type>
(e.g. ArrayList<Type>
or HashSet<Type>
).
Collection<? extends Type> getTypes();
Here, getTypes()
can return a Collection
of anything that is or extends Type
, (e.g. ArrayList<SubType>
or HashSet<SubType>
). So anything that can be returned from the first variant can also be returned from the second. In the second, however, you don't know what the type parameter of the collection actually is; you just know that it extends Type
.
As for which should be preferred, it really depends on what you're trying to do, and what makes more sense logically. Bear in mind that when you have <? extends Type>
, you don't actually know what ?
is, and this can be hindering at times; more often than not the first variant is more suitable. You can use the second variant in a base class and override it in subclasses with something that is more akin to the first, for instance:
@Override
Collection<SubType> getTypes() {
...
}
Returning with a wildcard type is generally discouraged, see the detailed reasons in the Generics FAQ. In short, it can make useless (or less useful) the returned object, because methods with parameters using the type argument can be called with 'null's only. For instance, with the Collection
:
Collection<? extends Type> collection = ...
collection.add(null); // OK
collection.add(anInstanceOfType); // Error
In this case, this prevents adding anything to the collection (which is not a bad thing, it seems someone uses this to try to make the returned collection "readonly", here), but in general this can cause problems.
<? extends Type>
is a bounding wildcard generic. A collection defined in this way could be of any subclass of type, or Type
. ie.
Collection<Type> typeCollection;
//or
Collection<SubType> subtypeCollection;
//where subtype is...
class SubType extends Type
All that matters in this case is that ?
is of type Type
.
Collection<Type>
must be return a collection of Type
. ie.
Collection<Type> collection;
Read the tutorials here. for more information. Which you chose will depend on your needs.
Here's an example. I use bounded wildcards when defining renderable item groups. For example.
public class SpriteGroup<T extends Sprite>
This would be a collection for Sprites, or any subclass of Sprite. This is useful because then I can define groups like so:
SpriteGroup<PhysicalSprite> physicalSprites = new SpriteGroup<PhysicalSprite>();
PhysicalSprite physicalSprite = physicalSprites.get(0);
SpriteGroup<ParticleSprite> particleSprite = new SpriteGroup<ParticleSprite>();
ParticleSprite particle = particleSprite.get(0);
Any get/set routines then return the type I specified (PhysicalSprite, ParticleSprite), which is desirable.
If I'd defined it as:
SpriteGroup<Sprite> spriteGroup = new SpriteGroup();
//all I can retrieve is a sprite, gotta cast now...
Sprite sprite = spriteGroup.get(0);
I'd need to cast them to access properties specific to each type of Sprite. Any subclass of SpriteGroup
would be restricted likewise.
来源:https://stackoverflow.com/questions/18382694/returning-collection-extends-type-vs-collectiontype