1

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
Community
  • 1
  • 1
committedandroider
  • 8,711
  • 14
  • 71
  • 126

2 Answers2

3

Can anyone describe or give an example of where this subtle difference actually makes a difference?

Yes. Two examples from the JDK:

You will note that the latter extends the former, yet what (sql) Date implements is Comparable of java.util.Date.

If it were "only" implementing Comparable of itself, you wouldn't be able to compare it to a "normal" Date.

Also consider the simple case of a Consumer (interface which appeared in Java 8). The most frequently used Consumer of all is System.out::println; its argument is an Object in this case.

Now, if the signature of Stream's .forEach() were .forEach(Consumer<T> consumer) instead of .forEach(Consumer<? super T>), you wouldn't be able to use that "universal consumer" at all, except for Stream<Object>s!

That is the CS part of the PECS rule (Producer Extends, Consumer Super).

fge
  • 119,121
  • 33
  • 254
  • 329
  • I think what you're trying to say is, with the second signature, `BinarySearchTree` is illegal, whereas it is legal with the first signature. – newacct Feb 22 '15 at 04:33
2

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 Dogs are comparable to themselves (in fact they are comparable to all Animals, which includes all Dogs). 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.

newacct
  • 119,665
  • 29
  • 163
  • 224
  • I understand that you would want a dog to be able to work with this data structure, but wouldn't the syntax be extends Animal> , that way dog would be a more specialized version of Animal and would work with this. super Animal> doesn't make as much sense to me because Dog is not a super class of Animal – committedandroider Feb 22 '15 at 21:06
  • @committedandroider: I don't understand what you mean. Where does `? extends Animal` come in? `BinarySearchTree extends Animal>` also works with the first signature but not the second. – newacct Feb 22 '15 at 21:18
  • Oh so the first one makes it so dog can implement Comparable of any of its superclass which it will because it extends Animal which extends Comparable? – committedandroider Feb 26 '15 at 07:53
  • @committedandroider: yes, `Dog` implements `Comparable` because it extends `Animal` which implements `Comparable` – newacct Feb 26 '15 at 10:36