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?
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 Dog
s 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<>()
.)