Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java Generics - Specifying upper bound on a class implementing an interface which itself specifies an upper bound

I have the following interface:

public interface ISort<T extends Comparable<T>> {
    public void sort(T[] array);
}

My understanding of this is that the the <T extends Comparable<T>> tells the compiler that within this class, there may be some generic types T, and they must be a Comparable<T> or be any class which implements Comparable<T>.

I then have the following class:

public class Sort<T extends Comparable<T>> implements ISort<T> {

    public void swap(T[] array, int i, int j) {
        T temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }

    public void sort(T[] array) {
        java.util.Arrays.sort(array);
    }

}

Again, I have the <T extends Comparable<T>> telling the compiler that within this class I will be using the type T which must form an IS-A relationship with Comparable<T>. However, why must I only type implements ISort<T>, why do I not need to write implements ISort<T extends Comparable<T>>? In order to help me understand this could you explain what exactly these generics statements are inferring to the compiler?

like image 867
Keir Simmons Avatar asked Dec 02 '25 17:12

Keir Simmons


2 Answers

There is a difference between specifying T with the class and using T in the extends or implements clause.

When specifying T with the class, you are declaring the type parameter T, but in the extends or implements clause, you are using a type parameter that is already declared.

public class Sort<T extends Comparable<T>>  // Declare T to be Comparable<T>
    implements ISort<T>                     // Use T

Using a type parameter in the extends or implements clause is no different than using the type parameter in the body of the class.

like image 112
rgettman Avatar answered Dec 05 '25 05:12

rgettman


The syntax for generic type usage is SomeType<SomeTypeArgument>.

In your case

class Sort<T extends Comparable<T>> implements ISort<T> {
        // ^ declares new type parameter             ^ uses it as a type argument 
        //                             

You declare a new type parameter T with bounds that match the expectations in the type parameter T declared in ISort. You can therefore use Sort#T as a type argument for ISort.

This would be similar to

class Sort implements ISort<Integer> {

The only difference is you don't declare a type parameter, you use an existing type.

like image 32
Sotirios Delimanolis Avatar answered Dec 05 '25 06:12

Sotirios Delimanolis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!