aspose file tools*
The moose likes Programmer Certification (SCJP/OCPJP) and the fly likes wildcards in generics Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Spring in Action this week in the Spring forum!
JavaRanch » Java Forums » Certification » Programmer Certification (SCJP/OCPJP)
Bookmark "wildcards in generics" Watch "wildcards in generics" New topic
Author

wildcards in generics

adithya narayan
Ranch Hand

Joined: Jan 05, 2009
Posts: 79

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
Matthew Brown
Bartender

Joined: Apr 06, 2010
Posts: 4422
    
    8

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

Joined: Jan 05, 2009
Posts: 79

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

Joined: Apr 06, 2010
Posts: 4422
    
    8

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

Joined: Apr 06, 2010
Posts: 4422
    
    8

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:


dennis deems
Ranch Hand

Joined: Mar 12, 2011
Posts: 808
Matthew, you've given us some really helpful posts here. Thanks!
Tommy Delson
Ranch Hand

Joined: Apr 13, 2011
Posts: 206


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



OCPJP6-05-11
"Your life is in your hands, to make of it what you choose."
Harsha Smith
Ranch Hand

Joined: Jul 18, 2011
Posts: 287
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

Joined: Jan 05, 2009
Posts: 79

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 !
nitin sethi
Ranch Hand

Joined: Jul 14, 2011
Posts: 59

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

Joined: Jul 14, 2011
Posts: 59

So Sorry, There was a typo in the method addToList at line 10. I am not adding to the parameter reference of the method.
 
Consider Paul's rocket mass heater.
 
subject: wildcards in generics