Java 泛型 list <?extends animal>和 list <Animal>

原文来自stakeoverflow     链接:http://stackoverflow.com/questions/2575363/generics-list-extends-animal-is-same-as-listanimal

The difference between List<Animal> and List<? extends Animal> is this: 

With List<Animal>, you know what you have is definitely a list of animals. It's not necessary for all of them to actually be exactly 'Animal's - they could also be derived types. For example, if you have a List of Animals, it makes sense that a couple could be Goats, and some of them Cats, etc - right?

For example this is totally valid:

List<Animal> aL= new List<Animal>();
aL.add(new Goat());
aL.add(new Cat());
Animal a = aL.peek();
a.walk();//assuming walk is a method within Animal

Just a sidenote - the following would not be valid:

aL.peek().meow();//we can't do this, as it's not guaranteed that aL.peek() will be a Cat

Of course if we're absolutely certain aL.peek() is a cat, we can do this:

((Cat)aL.peek()).meow();//will generate a runtime error if aL.peek() is not a Cat

With List<? extends Animal>, you're making a statement about the type of list you're dealing with.

For example:

List<? extends Animal> L;

This is actually not a declaration of the type of object L can holdIt's a statement about what kinds of lists L can reference.

For example, at this point,

L = aL;//remember aL is a List of Animals

would be something we could do.

But even after that assignment, all the compiler knows about L is that it is a List of [either Animal or a subtype of Animal]s

So now the following is not valid:

L.add(new Animal());//throws a compiletime error

Because for all we know, L could be referencing a list of Goats - to which we absolutely cannot add an Animal.

Why not? Well, let's see:

List<Goat> gL = new List<Goat>();//fine
gL.add(new Goat());//fine
gL.add(new Animal());//compiletime error

The reason the above doesn't work is we are attempting to cast an Animal as a Goat. That doesn't work, because what if after doing that we tried to make that Animal do a 'headbutt', like a goat would? We don't necessariliy know that the Animal can do that.



It is not. List<Animal> says that the value which is assigned to this variable must be of "type" List<Animal>. This however doesn't mean that there must only be Animal objects, there can be subclasses too.

List<Number> l = new ArrayList<Number>();
l.add(4); // autoboxing to Integer
l.add(6.7); // autoboxing to Double

You use the List<? extends Number> construct if you are interest in an list which got Numberobjects, but the List object itself doesn't need to be of type List<Number> but can any other list of subclasses (like List<Integer>).

This is sometime use for method arguments to say "I want a list of Numbers, but I don't care if it is just List<Number>, it can be a List<Double> too". This avoid some weird down casts if you have a list of some subclasses, but the method expects a list of the baseclass.

publid void doSomethingWith(List<Number> l) {
    ...
}

List<Double> d = new ArrayList<Double>();
doSomethingWith(d); // not working

This is not working as you expecting List<Number>, not a List<Double>. But if you wrote List<? extends Number> you can pass List<Double> objects even as they aren't List<Number> objects.

publid void doSomethingWith(List<? extends Number> l) {
    ...
}

List<Double> d = new ArrayList<Double>();
doSomethingWith(d); // works

Note: This whole stuff is unrelated to inheritance of the objects in the list itself. You still can add Double and Integer objects in a List<Number> list, with or without ? extends stuff.






  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值