这两种方法有什么区别?
Collection<Type> getTypes();
对比
Collection<? extends Type> getTypes();
Type 是类还是接口有关系吗?特别是在设计 API 时,首选哪个版本,为什么?
Collection<Type> getTypes();
在这里,getTypes()
必须返回一个Collection<Type>
(例如ArrayList<Type>
或HashSet<Type>
)。
Collection<? extends Type> getTypes();
在这里,getTypes()
可以返回一个Collection
是或扩展的任何东西Type
,(例如ArrayList<SubType>
或HashSet<SubType>
)。所以任何可以从第一个变体返回的东西也可以从第二个变体返回。但是,在第二种情况下,您不知道集合的类型参数实际上是什么;你只知道它扩展了Type
。
至于应该首选哪个,这实际上取决于您要做什么,以及在逻辑上更有意义的事情。请记住,当您拥有 时<? extends Type>
,您实际上并不知道是什么?
,这有时会造成阻碍;通常第一个变体更合适。您可以在基类中使用第二个变体,并在子类中用更类似于第一个的东西覆盖它,例如:
@Override
Collection<SubType> getTypes() {
...
}
通常不鼓励使用通配符类型返回,请参阅泛型常见问题解答中的详细原因。简而言之,它可以使返回的对象变得无用(或不太有用),因为使用类型参数的参数方法只能用'null'调用。例如,使用Collection
:
Collection<? extends Type> collection = ...
collection.add(null); // OK
collection.add(anInstanceOfType); // Error
在这种情况下,这可以防止向集合中添加任何内容(这不是一件坏事,似乎有人使用它来尝试使返回的集合“只读”,此处),但通常这会导致问题。
<? 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.