Using Extensions with Java Generics
Suppose I have the following code:
public class Shelter<A extends Animal, B extends Animal>
{
List<A> topFloor = new Vector<A>();
List<B> bottomFloor = new Vector<B>();
public A getFirstTopFloorAnimal(){return topFloor.get(0);}
public B getFirstBottomFloorAnimal(){return bottomFloor.get(0);}
//These 3 methods compile but when I try to use it, they all only return objects
public List<Animal> getAnimals()
{
List<Animal> a = new Vector<Animal>(topFloor);
a.addAll(bottomFloor);
return a;
}
public List<A> getTopFloor(){return topFloor;}
public List<B> getBottomFloor(){return bottomFloor;}
}
Then I'll try to do something like the following:
for(Animal a : shelter.getTopFloor()){
a.growl();
}
But I am a compiler error that I am getting the error that A is an object and not an animal. The same happens if I try other methods. Any idea why this is so? Is this because of something List<String>
not an idea List<Object>
in the Generics tutorial?
thanks
a source to share
Generics is only a compile time concept to improve type safety.
You cannot use them to filter values added to the collection at runtime. You have to do the filtering manually (for example using instanceOf
)
For example, this will work and allow you to add Date
:
List<String> list = new ArrayList<String>();
((List) list).add(new Date());
So the solution to your problem (not yet seen by us) is not to use the raw type when adding elements.
a source to share
My best guess is that you have declared to shelter
use a raw type like this:
Shelter shelter = new Shelter();
What you really need to do is:
Shelter<Cat,Dog> shelter = new Shelter<Cat,Dog>();
Then you are really using the generics functions.
see also
-
Effective Java 2nd Edition: Item 23: Don't use raw types in new code .
If you use raw types, you lose all the safety and expressiveness benefits of generics.
-
The use of raw types is allowed only as a concession to legacy code compatibility. The use of raw types in code written after the introduction of ancestry into the Java programming language is strongly discouraged. It is possible that future versions of the Java programming language will prohibit the use of raw types.
List<String>
Is notList<Object>
Yes, Java generics are not covariant or contravariant . It's only a problem if you're trying to apply one generic type to another, which doesn't seem to be what you are trying to do.
Also, contrary to what your topic title says, I don't think it has anything to do with extends
for binding type parameters in generics.
a source to share
This is because when you put elements in Vector
, they come in as objects, not instances Animal
.
public List<Animal> getAnimals()
{
Vector a = new Vector(topFloor); // <-- Not generic!
a.addAll(bottomFloor);
return a; // <-- Returning non-generic Vector.
}
Try this instead:
Vector<Animal> a = ...
a source to share