Reputation: 6848
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?
Upvotes: 0
Views: 99
Reputation: 9538
Simply put, List<? super Dog>
is a list of objects which have super
(parent) as Dog
, NOT a list of objects which are super
of Dog
Upvotes: 0
Reputation: 1785
Dog is an Animal so you can cast the ArrayList<? extends Dog>
to ArrayList<Animal>
but you can't go the other way since an Animal is not necessarily a Dog.
eg:
public class Cat extends Animal{}
Since this wouldn't make sense:
ArrayList<Dog> dogList = new ArrayList<Dog>();
dogList.add(new Cat());
You can't add an animal to the Dog list because the animal can be a cat.
This is an example of Java Type safety.
Upvotes: 0
Reputation: 198043
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<>()
.)
Upvotes: 4