7

Why does the following

public class ListBox {
    private Random random = new Random();
    private List<? extends Collection<Object>> box;

public ListBox() {
    box = new ArrayList<>();
}

public void addTwoForks() {
    int sizeOne = random.nextInt(1000);
    int sizeTwo = random.nextInt(1000);

    ArrayList<Object> one = new ArrayList<>(sizeOne);
    ArrayList<Object> two = new ArrayList<>(sizeTwo);

    box.add(one);
    box.add(two);
}

public static void main(String[] args) {
    new ListBox().addTwoForks();
}
}

Not work? Just toying around with generics for the purpose of learning and I expected that I would be able to insert anything that extends Collection in there but I get this error:

The method add(capture#2-of ? extends Collection<Object>) in the type List<capture#2-of ? extends Collection<Object>> is not applicable for the arguments (ArrayList<Object>)
The method add(capture#3-of ? extends Collection<Object>) in the type List<capture#3-of ? extends Collection<Object>> is not applicable for the arguments (ArrayList<Object>)

at ListBox.addTwoForks(ListBox.java:23)
at ListBox.main(ListBox.java:28)
arynaq
  • 6,710
  • 9
  • 44
  • 74
  • 2
    This answer on SO might help - http://stackoverflow.com/questions/2723397/java-generics-what-is-pecs – NG. Apr 30 '13 at 16:58

1 Answers1

13

You've declared box to be a List of something that extends Collection of Object. But according to the Java compiler, it could be anything that extends Collection, i.e. List<Vector<Object>>. So it must disallow add operations that take the generic type parameter for this reason. It can't let you add an ArrayList<Object> to a List that could be List<Vector<Object>>.

Try removing the wildcard:

private List<Collection<Object>> box;

This should work because you can certainly add an ArrayList<Object> to a List of Collection<Object>.

rgettman
  • 176,041
  • 30
  • 275
  • 357
  • This makes sense, but if I wanted to add a vector and an arraylist? Edit, link in first comment explains the use of super ;) – arynaq Apr 30 '13 at 17:08
  • 1
    @arynaq both of those implement List, so you could do `List> box`. Then you can add both Vectors and ArrayLists, though you can only get them out as `List`. If you need specific methods on `ArrayList` or `Vector`, you'll have to test-and-downcast or come up with something else -- but first make sure you really need that! – yshavit Apr 30 '13 at 17:09
  • 2
    Alternately, `List>` as suggested would already work for vectors and arraylists, as well as e.g. sets. – Louis Wasserman Apr 30 '13 at 17:10