Here is one declaration
public class BinarySearchTree<AnyType extends Comparable<? super AnyType>> {
....
}
Here is the other declaration
public class BinarySearchTree<AnyType extends Comparable<AnyType>>{
.....
}
I know the first declaration is preferred(seen it in alot of java examples and textbooks) but why is that? All my code ran fine when I tried using the second declaration as well.
I know that super used in this context, ? super AnyType, means AnyType or any of its super classes. Super
To me both are saying that this class, BinarySearchTree, supports any object type that is comparable. Can anyone describe or give an example of where this subtle difference actually makes a difference?
With dog example
class Animal implements Comparable<Animal>
class Dog extends Animal
public class BinarySearchTree<AnyType extends Comparable<? super AnyType>> {
...}
Would allow for
BinarySearchTree<Dog> but
public class BinarySearchTree<AnyType extends Comparable<AnyType>>{
.....
} wouldn't
If you have
class Animal implements Comparable<Animal>
class Dog extends Animal
then BinarySearchTree<Dog>
would be legal with the first signature but not with the second. It's not legal with the second signature because Dog
does not implement Comparable<Dog>
(and there is no way to make it implement Comparable<Dog>
, since it already implements Comparable<Animal>
, and a type cannot implement an interface with two different type arguments).
If you think about it, BinarySearchTree<Dog>
is perfectly fine because Dog
s are comparable to themselves (in fact they are comparable to all Animal
s, which includes all Dog
s). All we need is to guarantee someDog.compareTo(someOtherDog)
works. For this to work, we don't need that compareTo
take exactly Dog
-- any supertype of Dog
will also work. That's what the ? super
represents. It relaxes the constraint to a more general one that still provides all the type guarantees we need. In generics, we should always use the least restrictive bounds that give us the type safety we need.
Another way to think about it is through the PECS rule (Producer extends
, Consumer super
). A Comparable<T>
can only be a "consumer" of T
, because its only method takes a parameter of type T
, and it does not return T
. Therefore, Comparable
should always be used with a ? super ...
wildcard.