Reputation: 263220
What are the differences between the following three signatures?
static <T> void foo(List<T>, Comparator<? super T>);
static <T> void bar(List<? extends T>, Comparator<T> );
static <T> void baz(List<? extends T>, Comparator<? super T>);
I know what extends
and super
mean in Generics. My question is whether there is a difference between foo
, bar
and baz
. Should I make one of the parameters invariant and the other one variant in the appropriate direction, or should I make both of them variant? Does it make a difference?
Upvotes: 3
Views: 353
Reputation: 70574
The only difference is whether T
represents the type parameter of the List
, the Comparator
, or something in between.
As far as the caller is concerned, the three method signatures are equivalent, i.e. whenever one of them can be used, the others can be used as well.
For the method implementation foo
is probably most convenient, as it allows modifying the list without needing an additional capture conversion, which would require delegating to a helper method.
Upvotes: 2
Reputation: 146968
I believe that ? extends T
means that the List
may be generic of any type that is derived from T, whereas List<T>
can only be a List
of T
and not any of its derived classes.
Upvotes: 1
Reputation: 597234
PECS - Producer extends, consumer super.
To explain this "rule":
extends
means the genericized object produces elements of the type. When it's a collection, it means you can only take elements from the collection, but not put them in. The comparatorsuper
means the object consumes objects of the selected type. So you can add to the collection, but not read from it.Regarding the Comparator
, I don't think it makes any difference. Normally, it would be <? super T>
because you the comparator consumes objects, but in all three cases you can safely invoke Collections.sort(list, comparator);
(the signature of which is <? super T>
)
Upvotes: 5