Using generic collections in arguments
Let's say you have:
public interface A {}
public class B implements A {}
public class C {
void foo (List<A>) {}
}
public class Test {
//Declaration one
List<A> x = new List<A>();
//Declaration two
List<A> x = new List<B>();
B b = new B();
x.add(b);
new C().foo(x);
}
Now obviously declaration one is the correct way to do this, and you receive a compile error on declaration two. I would like to know though why Java chooses to enforce type safety in this specific manner; if a list o开发者_如何转开发f Cats is still a list of Animals, why does a method expecting a list of animals balk at receiving a bunch of cats?
Curiousity, more than anything else - and a chance to better refine my knowledge.
Cheers, Dave.
Java generics are not covariant. If you could do this:
ArrayList<Animal> x = new ArrayList<Cat>();
then you would be able to do:
x.add(new Dog());
which violates the concept that an ArrayList<Cat>
can only hold Cat
objects (or subclass objects).
Read this for for more details: Java theory and practice: Generics gotchas.
Why does a method expecting a list of animals balk at receiving a bunch of cats?
Because you can add any animal to that list, not just cats. This could result in a list of cats containing a dog, like so:
The caller still thinks it's a list of cats and a dog dies when the caller tries to make them fall on his feet when dropped.
Use "extends" instead of the class directly :
List<? extends A>x;
If you use only the class as generic then all the elements mus be only of this class.
精彩评论