2

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,

2
  • Out of interest, why would you use CollectionGeneric and not just use the List? Commented Jul 10, 2009 at 11:09
  • @Nick Holt: As I said at the beginning this a really simplyfied version of my problem, trust me, I have to use that CollectionGeneric class Commented Jul 10, 2009 at 11:13

1 Answer 1

7

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);
Sign up to request clarification or add additional context in comments.

1 Comment

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 sites.google.com/site/io/effective-java-reloaded

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.