I was looking over the TheAlgorithms repository for java and came to this first: https://github.com/TheAlgorithms/Java/blob/master/Searches/SearchAlgorithm.java. I see <T extends Comparable<T>>
, and I don't know what this means. I only know a little bit about generics and I know that the syntax has something to with parameter type bounds, but it would be great if someone could clarify how this has to do with Comparable<T>
, and what Comparable<T>
is.
There are some other questions on this forum similar to mine dealing with implementing <T extends Comparable<T>>
, but the answers haven't really clarified what Comparable<T>
is.
First, you have the Comparable
interface which roughly looks like:
public interface Comparable<T> {
int compareTo(T other);
}
As you can see, the type parameter of Comparable
is used as the parameter of the compareTo
method. Typically, the type argument for T
is the same class which is implementing the Comparable
interface. This generic setup facilitates comparing instances of the same type with each other. Here's an example:
public class Name implements Comparable<Name> {
@Override
public int compareTo(Name other) {
// compute & return result
}
}
Now let's say you have a method which should return the maximum of two objects according to their natural order. Such a method could look like the following:
public static <U extends Comparable<U>> U max(U left, U right) {
return left.compareTo(right) >= 0 ? left : right;
}
Note: Used U
as the type variable instead of T
to show it is separate from the T
used in the Comparable
interface.
The above is a generic method. The type variable U
is upper-bounded by Comparable<U>
. What this means is that the type argument used in place of U
must be assignable to (i.e. subtype of) Comparable<U>
. For instance, if we use Name
as the type argument it will work because Name
is assignable to Comparable<Name>
. The reason for specifying the upper-bound as Comparable<U>
is that the method needs to call compareTo
in order to function properly.
Name name1 = ...;
Name name2 = ...;
Name max = max(name1, name2); // U is inferred to be Name
As shown above, having U
as the return type also allows assigning the result to a variable of the same type as the arguments.
Note that for maximum flexibility the max
method should actually be declared like so:
public static <U extends Comparable<? super U>> U max(U left, U right) {
return left.compareTo(right) >= 0 ? left : right;
}
The difference being the use of Comparable<? super U>
as the upper-bound instead of Comparable<U>
. These two Q&As should help explain why using ? super U
offers greater flexibility: