2012-09-26 60 views
0

在过去,我已经能够实现一个通用的ArrayList铸造对象[]以E []:ClassCastException异常铸造对象[]以Trie.Node <V>而不是E []

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

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

我可以正常使用一般的阵列,像这样:

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

我想我可以实现类似的特里树:

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>(); 
} 

然而,在Trie.Node行public Node<V>[] next = (Node<V>[])new Object[26];导致一个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) 

所以它说我不能投的对象[]以Trie.Node []。

从Object []投射到E []和从Object []投射到Trie.Node <V> []是什么区别?为什么前者是允许的,而不是后者?

+0

请提高你接受的评价! – manub

回答

1

不同的是,泛型是通过擦除实现的,并给予无界限将擦除泛型类型为Object可用V[]

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

更多信息。 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找到更多关于擦除工作的信息。

+0

'Trie.Node []'将变成'Trie.Node []' – newacct

0

Node<V>[]数组不是V[]它工作在第一种情况,因为类型信息是E可用和ArrayList是使用强类型。

所以如果你删除泛型表单图片你正在做的是铸造Object[]Node[]这将导致类转换异常。

你可能想使用Generics Tutorial

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")

+0

没有类型参数的节点(节点')是否意味着节点? – indil

+0

对不起,我以前没有看到这个问题。不,这些不一样。由于节点不是节点,所以使用节点而不是节点将不编译。只需使用节点,就可以防止类型检查。这通常不是一个好主意,但可以在这里工作,因为最初所有元素都是空的,因此可以转换为任何类型,并且只添加节点元素,所以不会得到ClassCastException。 – herman