ConorW
ConorW

Reputation: 277

Generics (and Wildcards) in Java

A book I am reading on Java tells me that the following two pieces of code are equivalent:

public <T extends Animal> void takeThing(ArrayList<T> list)

public void takeThing(ArrayList<? extends Animal> list);

On the opposite page, I am informed that the latter piece of code uses the '?' as a wildcard, meaning that nothing can be added to the list.

Does this mean that if I ever have a list (or other collection types?) that I can't make them simultaneously accept polymorphic arguments AND be re-sizable? Or have I simply misunderstood something?

All help/comments appreciated, even if they go slightly off topic. Thanks.

Upvotes: 5

Views: 859

Answers (2)

Marko Topolnik
Marko Topolnik

Reputation: 200296

Usually, if adding to a list is involved inside a method that accepts just the list without the thing to add, you'll have somewhere else something that is an Animal and you'll want to add it to the list. In this case your method must be declared so that all the list types it accepts allow adding an Animal into them. This will have to be a List<Animal> or a list of some supertype of Animal. It can't possibly be a List<Dog>— the element you are adding could be any Animal.

This is where the concept of the lower bound, and the keyword super, come in. The type declaration List<? super Animal> matches all the acceptable types as described above. On the other hand, you won't be able to get elements out of such a list in a typesafe way because they can in general be of any type at all. If a method wants to both add and get elements of declared type Animal, the only valid type it can accept is a List<Animal>.

Upvotes: 1

Jesper
Jesper

Reputation: 207006

Does this mean that if I ever have a list (or other collection types?) that I can't make them simultaneously accept polymorphic arguments AND be re-sizable?

No.

The two pieces of code are not completely equivalent. In the first line, the method takeThing has a type parameter T. In the second line, you're using a wildcard.

When you would use the first version, you would specify what concrete type would be used for T. Because the concrete type is then known, there's no problem to add to the list.

In the second version, you're just saying "list is an ArrayList that contains objects of some unknown type that extends Animal". What exactly that type is, isn't known. You can't add objects to such a list because the compiler doesn't have enough information (it doesn't know what the actual type is) to check if what you're adding to the list should be allowed.

Upvotes: 3

Related Questions