1

Hi i have a query in below code.

When i declare list of animals it allows me to put Cat() and Dog() in it as they both are animal and satisfy IS A relation ship.

Class Cat extends Animal{}
Class Dog extends Animal{}

List<Animal> list = new ArrayList<Animal>();
list.add(new Dog());//Code works fine
list.add(new Cat());//Code works fine

Now here is my question if ? extends means accept anything that is subclass of Animal, then why is following code not compiling.

List<? extends Animal> list = new ArrayList<Animal>();
list.add(new Dog());//Compilation fails 
list.add(new Cat());//Compilation fails 

Same question , why dog is not accepted here ?

List<? extends Animal> dogs1 = new ArrayList<Dog>();
dogs1.add(new Dog());//Compilation fails

Can some one explain this behavior ?

Sachin Sachdeva
  • 10,526
  • 37
  • 100
  • This is definitely a duplicate, someone will flag it. Basically, your List could be of any subclass of Animal. If it were a List you wouldn't be able to add cats and vice versa. Because Java can't tell what it is, it doesn't allow you to add anything to it – Robin Topper Apr 30 '17 at 08:18
  • @Kayaman That is a weird "duplicate" – Robin Topper Apr 30 '17 at 08:34
  • Mods-Please check valid duplicate....:( else don't mark it as duplicate – Sachin Sachdeva Apr 30 '17 at 08:36

1 Answers1

2

A variable of type List<? extends Animal> can be assigned a List<Animal>, a List<Cat> or a List<Dog>. Some of these lists don't allow Dogs to be added to them, while others don't allow Cats.

The compiler validates the correctness of the list.add statements based on the compile time type of the list variable, not based on the actual object assigned to it in runtime. Therefore both list.add(new Dog()); and list.add(new Cat()); are not accepted.

If you wish to be able to add both Dogs and Cats, use a variable of type List<Animal>.

If you wish to only be able to add Dogs, use a variable of type List<Dog>.

Eran
  • 359,724
  • 45
  • 626
  • 694
  • @Eran- A variable of type List will do the same thing , then why List is working fine. – Sachin Sachdeva Apr 30 '17 at 08:21
  • Because the type is known at compile time, so the compiler can do the validations – Robin Topper Apr 30 '17 at 08:22
  • @ShowStopper A variable of type `List` can't be assigned a `List` or a `List`. Therefore you can safely add to it both `Dog`s and `Cat`s. – Eran Apr 30 '17 at 08:22
  • @Eran- List extends Animal> listAnimal = new ArrayList(); List listCat = listAnimal; this is also not valid in java – Sachin Sachdeva Apr 30 '17 at 08:24
  • @Eran- You can not assign A variable of type List extends Animal> to a List, a List or a List. I just checked . Will you please check again – Sachin Sachdeva Apr 30 '17 at 08:28
  • @ShowStopper I never said you can do that. I said you can assign a `List to a `List variable and a `List` to a `List` variable. – Eran Apr 30 '17 at 08:29
  • @ShowStopper `You can not assign A variable of type List extends Animal> to a List, a List or a List`. I said the opposite - you can assign a `List` to a `List extends Animal>` variable, not the other way. – Eran Apr 30 '17 at 08:31