Wild card in java Generic and <? super T> meaning, lower or upper bound
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);
Your method signature
public static <T> void selectionSort(T[] arr, Comparator<? super T> myComparator)
means that if you invoke it with an array of type T
than you must also provide a Comparator
of type T or a super type of T
.
For example if you have the following classes
class Vehicle {}
class Truck extends Vehicle {}
class BigTruck extends Truck {}
class VehicleComparator implements Comparator<Vehicle> {
public int compare(Vehicle o1, Vehicle o2) {
return 0;
}
}
class BigTruckComparator implements Comparator<BigTruck> {
public int compare(BigTruck o1, BigTruck o2) {
return 0;
}
}
class TruckComparator implements Comparator<Truck> {
public int compare(Truck o1, Truck o2) {
return 0;
}
}
then this will work
Truck[] trucks = ...;
selectionSort(trucks, new TruckComparator());
selectionSort(trucks, new VehicleComparator());
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
selectionSort(trucks, new BigTruckComparator());
Because a BigTruckComparator
is a Comparator<BigTruck>
and a BigTruck
is not a super type of the array's type Truck
.