Reputation: 1684
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?
Upvotes: 3
Views: 2006
Reputation: 20885
In the class declaration you introduce a type parameter with an upper bound. When you use T[]
as the type of the first parameter of the sort
method, you are not declaring anything (the declaration happens at the beginning of the file): you are merely using a type variable. Please, note the different phrasing:
Bounds on type parameters are only allowed at declaration site, and the declaration can happen in three places:
Here you a quick table:
// class
public static class Foo<T> {
// constructor
public <A> Foo() {}
// method
public <B> void doSomething() {}
// Not really allowed
// public void doSomethingElse(List<T extends Number> bar) {}
// here we have a wildcard, so you can do this
public void doSomethingElse(List<? super T> bar) {}
}
Upvotes: 0
Reputation: 280148
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.
Upvotes: 2
Reputation: 178313
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.
Upvotes: 3