我试图实现一棵树,使节点是通用的:

public class BinarySearchTree<U extends BinarySearchTree.Node, T extends Comparable<? super T>>
{
    public U root;
    ...

    public class Node {
        T data;
        U left;
        U right;

        public Node(T data) {
            this.data = data;
            left = null;
            right = null;
        }
    }
}


但是,当我尝试用一​​种方法进行赋值时,我得到了“预期的U,但发现BinarySearchTree.Node:

public void display(U root) {
    if (root != null) {
        display(root.left); // gives compile time error
        System.out.print(" " + root.data);
        display(root.right); // gives compile time error
    }
}

最佳答案

由于Node不是静态的,因此每个Node实例都属于一个包含BinarySearchTree的实例。但是,使用泛型无法指定它属于哪个泛型。因此,如果指定BinarySearchTree.Node,则它可以属于任何BinarySearchTree。由于您还使用了原始类型(请不要忽略警告!),因此不知道U是什么。因此,Java无法检查root.leftroot.right的类型是否相同,这就是为什么会出现此错误。

您可以通过如下指定类来修复编译错误:

class BinarySearchTree<U extends BinarySearchTree<U,T>.Node, T extends Comparable<? super T>>
{ ... }


但这不能解决潜在的问题,即节点可以属于任何包含BinarySearchTree的节点,而这可能不是您想要的。

如果您确实想使用通用节点类型,则可以将其设置为静态,这样它就不再属于包含实例了:

public static class Node<U,T>
{
    ...
}


但是我质疑是否首先需要有一个通用节点类。通常,此类节点被视为实现细节,您希望完全控制从您的类中创建它们。这不适用于通用节点,因为您的类不知道要实例化哪种节点。

因此,我将按以下方式定义您的BinarySearchTree类:

public class BinarySearchTree<T extends Comparable<? super T>>
{
    private Node<T> root;

    private static class Node<T>
    {
        T data;
        Node<T> left;
        Node<T> right;
    }

    ...
}

10-06 08:33