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:
- Defined vehicle class
- created VehicleComparator implementing Comparator while compare vehicles by their price.
- created Truck extends vehicle
- instantiated Truck[] arr ; VehicleComparator myComparator
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!
The quizzical phrase
? super T
means that the destination list may have elements of any type that is a supertype ofT
, just as the source list may have elements of any type that is a subtype ofT
.We can see pretty simple example
copy
fromCollections
:And call:
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:
The two signatures are equivalent in terms of power -- for any set of arguments, if there exists a choice of type arguments that works for one of them, there exists a choice of type arguments that works for the other one, and vice versa.
You are simply running into limited inference in your compiler. Simply explicitly specify the desired type argument:
Firstly, you could have solved it by having
Vehicle[]
which you then addedTruck
s to.The reason you need
<? super T>
goes back to the generics rule thatComparator<Truck>
is not a subtype ofComparator<Vehicle>
; the unbounded typeT
must match exactly, which it doesn't.In order for a suitable
Comparator
to be passed in, it must be aComparator
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 theComparator
is, as long as it's a supertype of the array's component type.Your selection sort method
means that if you invoke it with an array of type
T
than you must also provide aComparator
of type T or a super type ofT
.For example if you have the following classes
than this will work
because
TruckComparator
implementsComparator<Truck>
and aTruck
is equal to the array's typeTruck
VehicleComparator
implementsComparator<Vehicle>
and aVehicle
is a super type of the array's typeTruck
This will NOT WORK
and you should guess now why.
Because a
BigTruckComparator
is aComparator<BigTruck>
and aBigTruck
is not a super type of the array's typeTruck
.