So I am reading about generic method and I am get confused. Let me state the problem here first:
In this example: Suppose that I need a version of selectionSort that works for any type T, by using an external comparable supplied by the caller.
First attempt:
public static <T> void selectionSort(T[] arr, Comparator<T> myComparator){....}
Suppose that I have:
Now, I do:
selectionSort(arr, myComparator);
and it won't work, because myComparator is not available for any subclass of Vehicle.
Then, I do this:
public static <T> void selectionSort(T[] arr, Comparator<? super T> myComparator){....}
This declaration will work, but I don't completely sure what I've been doing... I know use is the way to go. If "? super T" means "an unknown supertype of T", then am I imposing a upper or lower bound? Why is it super? My intention is to let any subclass of T to use myComparator, why "? super T". So confused... I'd appreciate if you have any insight in this..
Thanks ahead!
Firstly, you could have solved it by having Vehicle[]
which you then added Truck
s to.
The reason you need <? super T>
goes back to the generics rule that Comparator<Truck>
is not a subtype of Comparator<Vehicle>
; the unbounded type T
must match exactly, which it doesn't.
In order for a suitable Comparator
to be passed in, it must be a Comparator
of the class being compared or any super class of it, because in OO languages any class may be treated as an instance of a superclass. Thus, it doesn't matter what the generic type of the Comparator
is, as long as it's a supertype of the array's component type.
The quizzical phrase ? super T
means that the destination list may have elements of any type
that is a supertype of T
, just as the source list may have elements of any type that is a
subtype of T
.
We can see pretty simple example copy
from Collections
:
public static <T> void copy(List<? super T> dst, List<? extends T> src) {
for (int i = 0; i < src.size(); i++) {
dst.set(i, src.get(i));
}
}
And call:
List<Object> objs = Arrays.<Object>asList(2, 3.14, "four");
List<Integer> ints = Arrays.asList(5, 6);
Collections.copy(objs, ints);
assert objs.toString().equals("[5, 6, four]");
As with any generic method, the type parameter may be inferred or may be given explicitly. In this case, there are four possible choices, all of which type-check and all of which have the same effect:
Collections.copy(objs, ints);
Collections.<Object>copy(objs, ints);
Collections.<Number>copy(objs, ints);
Collections.<Integer>copy(objs, ints);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With