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

+2


a source to share


4 answers


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.

+4


a source


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.

  • JLS 4.8 Raw Types

    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 not List<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.

+2


a source


I think the crux of your problem is here:

for(Animal a : shelter.getTopFloor()){
    a.growl();
}

      

How is it determined shelter

?

+1


a source


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 = ...

      

0


a source







All Articles