Search code examples
javagenericssuperbounded-wildcard

Difference between using `? super` in parameter and variable


I thought I'd figured out generics with super. But I must be completely wrong:

With this simple example:

class Animal{}
class Dog extends Animal{}

This code works fine because we are passing in a super class of Dog:

static void addThis(ArrayList<? super Dog> a) {
    a.add(new Dog());
}
...
ArrayList<Animal> dogs=new ArrayList();
addThis(dogs);

However, what I don't understand is I thought this is the same thing:

ArrayList<? super Dog> dogs2=new ArrayList();
dogs2.add(new Animal());

But it fails to compile. What is the difference between the two?


By the way, I'd like to sneak in another question. Is there any difference between

// This...
ArrayList<Animal> dogs=new ArrayList();
// ... and this?
ArrayList<Animal> dogs=new ArrayList<Animal>();

Given type erasure removes it at compile time I figure it's the same thing as the compiler is checking the reference type. Is this correct?


Solution

  • It's not at all the same thing. In one case you're adding a Dog, in the other case you're adding an Animal.

    In both cases you only know that Dogs are allowed, so the second case fails.

    To answer your second question, there is a difference, and you should always use the second version. (In Java 7+, however, you can request the compiler to infer the generic type for you by writing new ArrayList<>().)