2012-09-26 119 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