Returning Collection<? extends Type> vs Collection<Type>

本秂侑毒 提交于 2019-12-07 11:13:37

问题


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?


回答1:


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() {
    ...
}



回答2:


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.




回答3:


<? 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!