【问题标题】:Generic types in an array for a tree with more than one child具有多个孩子的树的数组中的泛型类型
【发布时间】:2013-04-04 03:39:25
【问题描述】:

我正在尝试实现具有多个孩子的树,我需要以某种方式存储这些孩子。我决定可以使用LinkedList,但我想先尝试使用数组。

(请不要使用任何 Imports。)

class Node<T extends Comparable<? super T>>
{
    Node<T> arrChildren[] = new Node<T>[size];
}

这不起作用。

class Node<T extends Comparable<? super T>>
{
    Comparable<Node<T>> arrChildren[] = new Comparable[size];
    T element;
}

这可行,但我无法将 arrChildren[0] 与普通的 Node&lt;T&gt; 进行比较,如果我将所有的 Node&lt;T&gt;s Comparable 节点都设置为节点,我将无法到达内部的元素。

这是我在 Stack Overflow 上的第一篇文章,希望也能得到很好的回应,我不介意批评。

谢谢。

【问题讨论】:

    标签: java arrays generics types tree


    【解决方案1】:

    泛型和数组在 Java 中不能很好地混合。像您考虑的那样使用List&lt;T&gt; 实现会容易得多:

    List<Node<T>> arrChildren = new LinkedList<>();
    

    更长的解释:

    数组:

    • 在运行时跟踪它们的组件类型。
    • 是协变的(Integer[]Number[]Object[])。

    通用类型:

    • 编译器将它们的类型参数erased 设置为在运行时不可用。对 Node&lt;String&gt; 的调用变成对 Node 的调用,并适当地转换为 String
    • 不是协变的(List&lt;Integer&gt;不是List&lt;Number&gt;)。

    不允许new Node&lt;T&gt;[size] 的原因是数组需要在运行时知道其组件类型,此时不再有T 的概念。只有new Node&lt;?&gt;[size] 这样的东西是允许的。

    忽略创建Node&lt;T&gt; 数组的限制,仅仅引用一个是不安全的,因为以下情况是可能的:

    Node<Integer>[] intNodeArray = ...;
    Object[] objArray = intNodeArray; //legal because arrays are covariant
    objArray[0] = new Node<String>("asfd"); //should fail but doesn't
    
    ...
    
    //sometime later
    Node<Integer> intNode = intNodeArray[0]; //still doesn't fail because of erasure
    Integer i = intNode.getValue(); //only now do we get a runtime exception
    

    向数组添加Node&lt;String&gt;应该抛出运行时异常,但不会因为数组只知道它的组件类型是Node,而不是Node&lt;Integer&gt;。 p>

    有关详细信息,请参阅 Angelika Langer 的泛型常见问题解答:Can I create an array whose component type is a concrete parameterized type?

    【讨论】:

    • 您好,感谢您的回复。我最终使用了这个“Node [] arrChildren = new Node[size];”结合类声明中的可比性,它实际上工作得很好。我可以访问 arrChildren[0].elements;。这只是不好的做法吗?我认为我的工作有效,因为在这种情况下,我实际上想要一个对节点的引用,并以我永远不会与引用的内存失去联系的方式对我的树进行编程。这有意义吗?我不想从一开始就使用 List,因为如果我想使用 Linked List,我必须自己制作。
    • @Enfodo 应该没问题,只要您将其隐藏为实现细节并了解我演示的场景 - 我没有意识到您实际上无法导入任何内容。
    【解决方案2】:
    Node<T>[] arrChildren = (Node<T>[])new Node<?>[size];
    

    【讨论】:

    • 嗨,谢谢我最终使用了这个。除了我排除了 (Node[])。据我所知,这是一个转换,我会用它来使浮点数成为整数,但在这种情况下它会做什么?谢谢。
    • @Enfodo 您正在使用new Node[size],其中普通的Node 是原始类型。它隐含地在做与这个答案相同的事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-04
    • 2018-05-15
    • 2023-03-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多