views:

282

answers:

1

Hi, There is any way to fix this situation (I have try to simplyfy the scenario as much as i could):

public class Test {

  public static void main(String [] args) {

        /* HERE I would like to indicate that the CollectionGeneric
           can be of something that extends Animal (but the constructor 
           doesn't allow wildcards) */
        CollectionGeneric<? extends Animal> animalsCollectionGeneric = 
                 new CollectionGeneric<Animal>(); 
      List<? extends Animal> animals = getAnimals();
        /* Why I cannt do that? */ 
       animalsCollectionGeneric.setBeans(animals);
    }

    private static List<? extends Animal> getAnimals() {
     return new ArrayList<Dog>();
    }
}

class CollectionGeneric<T> {
private List<T> beans;

public List<T> getBeans() {
 return (beans != null) ? beans : new ArrayList<T>();
}

public void setBeans(List<T> beans) {
 this.beans = beans;
}
}

interface Animal {}

class Dog implements Animal{}

this scenario is giving me the next error:

The method setBeans(List<capture#2-of ? extends Animal>) in the type    
CollectionGeneric<capture#2-of ? extends Animal> is not applicable for
the arguments (List<capture#3-of ? extends Animal>)*

I am not sure about if there is a way to do this with generics,

+5  A: 

What this means is that the two collections can not be proved to have the same type bounds:

    CollectionGeneric<? extends Animal> animalsCollectionGeneric = 
             new CollectionGeneric<Animal>(); 
    List<? extends Animal> animals = getAnimals()

The first one might at runtime have CollectionGeneric<Tiger> and the second one List<Gnu>. Mixing those would mean you lose the type safety ( not to mention the carnage ).

Therefore you need to prove to the compiler that those two are related, so your generic signatures should be:

public void setBeans(List<? extends T> beans) {}
public List<T> getBeans();

and used as:

List<? extends Animal> beans = getBeans();
GenericCollection<Animal> animals = new GenericCollection<Animal>();
animals.add(beans);
Robert Munteanu
Good answer. Note that if you wanted to add an addBeans() method, it could simply take an object of type T. Josh Bloch gave a talk that went into generics and wildcards at Google I/O. See http://sites.google.com/site/io/effective-java-reloaded
NamshubWriter