java - 为什么我不能分配给这个通用变量?

标签 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;
        }
    }
}

但是当我尝试在我的一种方法中进行赋值时,我得到一个“Expected U but found 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;
    }

    ...
}

关于java - 为什么我不能分配给这个通用变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51298255/

相关文章:

c# - 拥有通用比较器的最佳方法是什么

java - 如何使用 Spring-data-mongodb 根据月份对日期进行分组并获取每个月的最新值?

java - 每次统计完出现次数后将结果添加到int数组

设置 TextArea 和 StyleSheets/css 背景颜色的 Java 7 到 Java 8 问题

java - 如何访问 JPQL 查询结果的对象数组列表

java - 加载内部类而不加载封闭类

java - 使用 DOM 解析器解析 XML 字符串返回 null

java - 具有多态泛型的映射

android - BroadcastReceiver 作为内部类

java - Android & Java 内部类概念