Java 泛型 list

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

The difference between List and List is this: 

With List, 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, 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 says that the value which is assigned to this variable must be of "type" List. 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 construct if you are interest in an list which got Numberobjects, but the List object itself doesn't need to be of type List but can any other list of subclasses (like List).

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, it can be a List 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, not a List. But if you wrote List you can pass List objects even as they aren't List 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 list, with or without ? extends stuff.






你可能感兴趣的:(Java语言基础)