0

过去,我可以通过将 Object[] 转换为 E[] 来实现一个通用的 ArrayList:

public class ArrayList<E>
{
    private E[] elements;

    @SuppressWarnings("unchecked")
    public ArrayList()
    {
        elements = (E[])new Object[16];
    }
 }

我可以正常使用泛型数组,如下所示:

public void add(E element)
{
    ...
    elements[size++] = element;
}

我想我可以类似地实现一个 trie:

public class Trie<V>
{
    private static class Node<V>
    {
        public V value;
        @SuppressWarnings("unchecked")
        public Node<V>[] next = (Node<V>[])new Object[26];
    }

    private Node<V> root = new Node<V>();
}

但是,public Node<V>[] next = (Node<V>[])new Object[26];Trie.Node 中的行会导致 ClassCastException:

public class Main
{
    public static void main(String[] args)
    {
        ArrayList<Integer> a = new ArrayList<Integer>();
        Trie<Integer> t = new Trie<Integer>();
    }
}

java Main
Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [LTrie$Node;
    at Trie$Node.<init>(Trie.java:6)
    at Trie$Node.<init>(Trie.java:3)
    at Trie.<init>(Trie.java:10)
    at Main.main(Main.java:6)

所以它说我不能将 Object[] 转换为 Trie.Node[]。

从 Object[] 转换为 E[] 和从 Object[] 转换为 Trie.Node<V>[] 有什么区别?为什么前者被允许而不是后者?

4

3 回答 3

2
public Node<V>[] next = (Node<V>[])new Object[26];

应该改为

public Node<V>[] next = (Node<V>[])new Node[26];

甚至

public Node<V>[] next = new Node[26];

因为无论如何都不会检查演员阵容,并且两种形式都需要@SuppressWarnings("unchecked")

于 2012-09-26T11:47:32.687 回答
1

不同之处在于泛型是通过擦除实现的,并且不给出边界会将泛型类型擦除为Object. E[]会变成Object[],一会儿Trie.Node<V>[]会变成Trie.Node<Object>[]。因此,(Node<V>[])new Object[26];当您尝试转换Object[]Node<Object>[].

您可以在http://docs.oracle.com/javase/tutorial/java/generics/erasure.html找到有关擦除工作原理的更多信息。

于 2012-09-26T09:25:59.240 回答
0

Node<V>[] 数组不是V[]它在第一种情况下有效,因为类型信息是 E 可用并且 ArrayList 使用强类型。

因此,如果您从图片中删除泛型,那么您正在做的就是强制转换Object[]Node[]这将导致类强制转换异常。

您可能想使用V[]

public V[] next = (V[])new Object[26];

有关泛型教程的更多信息

于 2012-09-26T09:23:14.100 回答