In the past, I’ve been able to implement a generic ArrayList by casting Object[] to E[]:
public class ArrayList<E>
{
private E[] elements;
@SuppressWarnings("unchecked")
public ArrayList()
{
elements = (E[])new Object[16];
}
}
and I could use the generic array normally, like so:
public void add(E element)
{
...
elements[size++] = element;
}
I thought I could implement a trie similarly:
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>();
}
However, the line public Node<V>[] next = (Node<V>[])new Object[26]; in Trie.Node causes a 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)
So it’s saying I can’t cast Object[] to Trie.Node[].
What’s the difference between casting from Object[] to E[] and casting from Object[] to Trie.Node<V>[]? Why is the former permitted and not the latter?
The difference is that generics are implemented via erasure, and giving no bounds will erase that generic type into
Object.E[]will becomeObject[], whileTrie.Node<V>[]will becomeTrie.Node<Object>[]. Hence,(Node<V>[])new Object[26];is a invalid cast as you’re trying to castObject[]toNode<Object>[].You can find more information about how erasure works at http://docs.oracle.com/javase/tutorial/java/generics/erasure.html.