为什么不能分配给该通用变量?

时间:2018-07-12 05:58:58

标签: java generics inner-classes nested-generics

我正在尝试实现一棵树,以使节点通用:

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
    }
}

2 个答案:

答案 0 :(得分:2)

由于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;
    }

    ...
}

答案 1 :(得分:1)

您应该将类​​定义重写为

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