0

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?

Paul Bellora
  • 54,340
  • 18
  • 130
  • 181
Neil Walker
  • 6,400
  • 14
  • 57
  • 86
  • I hope you don't mind that I rolled back your edit, so that the answers would make sense. Feel free to ask a new question if you still have doubts about anything. – Paul Bellora Feb 13 '13 at 04:26

3 Answers3

4

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<>().)

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
  • Sorry, I completely messed up my question. My mind was in a different place due to getting confused. The real question was about, well, what I've updated it to (I didn't expect an answer so soon!), i.e. I thought super meant The item or a supertype can be added. – Neil Walker Feb 12 '13 at 23:23
  • `? super Dog` means there is _some unknown_ superclass of `Dog` which you're restricted to. That could be `Dog` itself, which would forbid `Animal`, or it could be `Object`, in which case you could add anything. But the only thing you _know_ is allowed is `Dog`. – Louis Wasserman Feb 12 '13 at 23:25
  • Ah, I see the light now. I was thinking the ?super extended to what you put in it as well. So as long as what I pass in is the same or super type then we know we can add any subtype. Thanks. – Neil Walker Feb 12 '13 at 23:33
0

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.

enrybo
  • 1,787
  • 1
  • 12
  • 20
0

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

anoopelias
  • 9,240
  • 7
  • 26
  • 39
  • Seems you put what I was thinking at the same time (I added a comment above): I was thinking the ?super extended to what you put in it as well. So as long as what I pass in is the same or super type then we know we can add any subtype. Thanks. – Neil Walker Feb 12 '13 at 23:35