Implementing Binary Tree in Java with Generic Comp

2019-09-07 18:14发布

问题:

Q: In my implementation of a binary tree below, why does the compiler choke at

if (data.compareTo(this.data) <= 0),

producing

Error: incompatible types: java.lang.Comparable<T> cannot be converted to T?

Both data and this.data are of type Comparable<T> and should be able to use or be an argument to the compareTo() method...right? Well, clearly not. But I really don't understand why. Generics are still baffling me.

public class MyBinaryTreeNodeG<T>{
  Comparable<T> data;
  MyBinaryTreeNodeG<T> parent;
  MyBinaryTreeNodeG<T> left;
  MyBinaryTreeNodeG<T> right;

  public MyBinaryTreeNodeG(Comparable<T> data){
   this.data = data; 
  }

  public MyBinaryTreeNodeG<T> addChild(Comparable<T> data){
    if (data.compareTo(this.data) <= 0) { //this is the line on which the compiler chockes
    //check if left tree node is null. If so, add. Otherwise, recurse.
    } else {
    //same for the right tree node
    return null;
  }  

The following is a clip from a more standard implementation of a binary tree. This compiles fine. But I still fail to see why this is a "better" (according to compiler) implementation than mine above.

public class MyBinaryTreeNodeG<T extends Comparable<T>>{
  T data;
  MyBinaryTreeNodeG<T> parent;
  MyBinaryTreeNodeG<T> left;
  MyBinaryTreeNodeG<T> right;

  public MyBinaryTreeNodeG(T data){
   this.data = data; 
  }

  public MyBinaryTreeNodeG<T> addChild(T data){
    if (data.compareTo(this.data) <= 0) {
      //left node stuff
    } else { 
     //right node stuff
    return null;
  }

回答1:

Look at the javadoc of Comparable : compareTo(T) is provided by the Comparable interface. This method allows to compare a object instance of T class implementing this interface with another T instance. In your first example, you're comparing a Comparable<T> with a Comparable<T> (and not with T)

This should work :

public class MyBinaryTreeNodeG<T> {

    Comparable<T> data;

    // ...

    public MyBinaryTreeNodeG<T> addChild(final T data) {
        if (this.data.compareTo(data) <= 0) {
        } else {
        }
        // ...
    }
}


回答2:

If something is Comparable<T>, it is comparable to a T, not comparable to a Comparable<T>. That's why the second snippet works.