• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

wildcards in generics

 
Ranch Hand
Posts: 79
Android Eclipse IDE Firefox Browser
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,

I have written this particular piece of code :



It can be seen that in the main() i am adding both cats and dogs and passing the list in addAnimal() method where i am again adding a dog. Why does the compiler let me do that ??

Secondly,
If i modify the addAnimal() method to add an Animal instead of a Dog then why doesn't the compiler let me do so ? Is it like it will allow me to add only Dog and nothing else ?

Can anyone please explain ?


Thanks,
Adithya
 
Bartender
Posts: 4568
9
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You can add both Cats and Dogs in the main method because it's a List<Animal>. Dogs and cats are both animals, so there's no problem there.

In the addAnimal method, it's declared as a List<? super Dog>. So it could be a List<Dog>, a List<Animal>, or a List<Object>. The one thing you can guarantee is that it will be able to accept a Dog, and all subclasses of Dog. But you couldn't add a Cat at this point, because that isn't safe (e.g. if it turns out to be a List<Dog>).

Does that help? I think the easiest way to understand wildcards is to ask "what actual types are allowed here?". If the operation makes sense for all possible types, then it makes sense for the wildcard. If it won't work for just one possible type, then you can't do it.
 
adithya narayan
Ranch Hand
Posts: 79
Android Eclipse IDE Firefox Browser
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Matthew Brown wrote:You can add both Cats and Dogs in the main method because it's a List<Animal>. Dogs and cats are both animals, so there's no problem there.



So, in a way we are breaking the code by adding Cats,Dogs, etc.(various subclasses of Animal) in the main() and passing the list to the addAnimal() method right ? It means we need to be careful by taking necessary precautions so that nothing unexpected gets entered into the type-checked list ? Isn't that an overhead for a developer. It's quite possible that by mistake a developer might not be aware of what he is adding into the type-checked list in the main() right ?

Matthew Brown wrote:
In the addAnimal method, it's declared as a List<? super Dog>. So it could be a List<Dog>, a List<Animal>, or a List<Object>. The one thing you can guarantee is that it will be able to accept a Dog, and all subclasses of Dog. But you couldn't add a Cat at this point, because that isn't safe (e.g. if it turns out to be a List<Dog>).



Here lies my question. If we tell the addAnimal(List<? super Dog> animals) method that please accept any list which is of type Dog or higher than that then ideally it should also let me add anything that is of type Dog or anything higher than that. Why does it restrict me to add only Dog or its subclasses? Probably, i am missing something

Matthew Brown wrote:
Does that help? I think the easiest way to understand wildcards is to ask "what actual types are allowed here?". If the operation makes sense for all possible types, then it makes sense for the wildcard. If it won't work for just one possible type, then you can't do it.



Exactly, the addAnimal(List<? super Dog> animals) method says the actual types allowed are Dog,Animal and Object then it should let me add all three of them in the incoming list.

The whole question arises because <? super Animal> lets you add whereas <? extends Animal> doesn't. Nowhere did i read about the restrictions on the types being added.


Thanks,
Adithya.
 
Matthew Brown
Bartender
Posts: 4568
9
  • Likes 2
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

adithya narayan wrote:So, in a way we are breaking the code by adding Cats,Dogs, etc.(various subclasses of Animal) in the main() and passing the list to the addAnimal() method right ?


Not really. The list is declared in main() as a List<Animal>- presumably that's for a reason? If you didn't want to be able to add any Animal you want to it, you'd have declared it as a List<Dog> in the first place.

adithya narayan wrote:Here lies my question. If we tell the addAnimal(List<? super Dog> animals) method that please accept any list which is of type Dog or higher than that then ideally it should also let me add anything that is of type Dog or anything higher than that.



No. That's a common mistake, but that's not what it means. It doesn't mean that you've got a list that can take any type higher than Dog. It means that you've got a specific List of an unknown type (where the unknown type is a Dog or higher). So, for instance, it could be a List<Dog>. What would you expect to be able to add to that?


List<? extends Animal> works under similar principles. The actual List has to be of a specific type, and that type can be Animal or any subclass. So it could be a List<Animal>, List<Dog>, List<GoldenRetriever>, List<Mouse>, etc. Can you think of any object that would be safe to add into all those? There isn't one. That's why you can't add anything to a List<? extends Xxx>.
 
Matthew Brown
Bartender
Posts: 4568
9
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Just to add to the above, in case it helps: remember that you can't create an ArrayList<? super Dog>, or any other object with a generic wildcard. You can have a reference variable of that type, but it must point at an instance of a specific generic type.

In other words:


 
Ranch Hand
Posts: 808
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Matthew, you've given us some really helpful posts here. Thanks!
 
Ranch Hand
Posts: 206
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


An addition of what left off, but important....what do you think about this?

 
Ranch Hand
Posts: 287
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
List<? super Animal> list4 = new ArrayList<Dog>(); //Allow or not, and why?

won't compile.....type mismatch.

Dog is not super of animal..it is sub of animal

List<? super Animal> list5 = new ArrayList<Object>(); // compiles but can add only animals

and also make the animal class Abstract
 
adithya narayan
Ranch Hand
Posts: 79
Android Eclipse IDE Firefox Browser
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Matthew Brown wrote:

adithya narayan wrote:Here lies my question. If we tell the addAnimal(List<? super Dog> animals) method that please accept any list which is of type Dog or higher than that then ideally it should also let me add anything that is of type Dog or anything higher than that.



No. That's a common mistake, but that's not what it means. It doesn't mean that you've got a list that can take any type higher than Dog. It means that you've got a specific List of an unknown type (where the unknown type is a Dog or higher). So, for instance, it could be a List<Dog>. What would you expect to be able to add to that?



Got it ! addAnimal(List<? super Dog> animals) means surely its going to be a List of Dogs or its parents and since, its sure that its going to be from the hierarchy of Dog, it lets me add only Dogs and its subclasses.

Thanks a lot Matthew !
 
Ranch Hand
Posts: 59
Android Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

List<? extends Animal> works under similar principles. The actual List has to be of a specific type, and that type can be Animal or any subclass. So it could be a List<Animal>, List<Dog>, List<GoldenRetriever>, List<Mouse>, etc. Can you think of any object that would be safe to add into all those? There isn't one. That's why you can't add anything to a List<? extends Xxx>.



I wonder why the below code compiles and run still? We are allowed to add an object of class B here.

 
nitin sethi
Ranch Hand
Posts: 59
Android Eclipse IDE Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So Sorry, There was a typo in the method addToList at line 10. I am not adding to the parameter reference of the method.
reply
    Bookmark Topic Watch Topic
  • New Topic