2

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.

mpnm
  • 371
  • 1
  • 4
  • 11

3 Answers3

4

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:

Slaw
  • 30,631
  • 6
  • 43
  • 69
  • Why isn't `U max(U left, U right)` in the curly brackets of the method, in your example? – mpnm Nov 05 '19 at 23:44
  • 1
    That `U` is the return type of the method. The type variable `U` is, however, declared in angle brackets which is what allows using `U` as the return type: `> U max(U left, U right)`. Or did I misunderstand your question? – Slaw Nov 05 '19 at 23:48
1

To clarify, we can decompose this puzzling-looking expression into its elements and put them back together.

Premise

We have a method find(? array[], ? key) that looks for a key within an array. We want to use this method for different types of input arguments, e.g., an array/key of String, Integer, whatever.

Parametric Type <U>

We put <U> in front of the method signature to indicate that it is a parametric method. This means that in the rest of the declaration, U is a placeholder that will be replaced by a type where the method is invoked. (I use U instead of T for reasons that will become obvious below.)

But, we can't replace U with any type because to be able to correctly implement the method, we want to be able to compare the elements in the array to each other (for instance to sort the array). The common interface used to define this behavior is Comparable. It has a single method, compareTo.

Type Bound <U extends Comparable>

To require that the U type parameter only be replaceable (instantiable) with a type that is a subtype of Comparable, we impose the type bound: extends Comparable. This allow us to call compareTo on key or on array elements such as array[0] in a type safe way.

However, we're not done here, because Comparable is itself a generic type: Comparable<T>, where the type parameter T governs the type of the parameter for compareTo. We thus need to instantiate T when we use Comparable<T>.

Instantiating Comparable<T>

Before instantiating T in Comparable, our expression is <U extends Comparable<T>>. We need to replace T with the desired type. What should be the type of the parameter to compareTo? If we are passing an array of String to find, we would be comparing Strings, etc. In the generic case we are passing an array of U to find, so we would like to compare objects of type U. So in this case we instantiate T in Comparable<T> with another generic type, U: <U extends Comparable<U>>, which is the same as <T extends Comparable<T>>

SDJ
  • 4,327
  • 1
  • 17
  • 33
0

It means that T is a class type which is subtype of or inheriting Comparable which also accepts a generic type and it should be of same type as the class which is represented by T here.

E.g.

replace T by Employee class and Employee class definition is as below.

Employee is now T and Comparable's compareTo method must also accept Employee as parameter as T is now Employee per Comparable.

class Employee implements Comparable<Employee>{

    @Override
    public int compareTo(Employee o) {
        return 0;
    }
}
Vinay Prajapati
  • 6,621
  • 6
  • 42
  • 80