1

Im creating an inner class in Java that uses outer class' parameterized types as instance fields. Now when I try to create an arrayof this innerclass, I get classcast exception

 class ModdedSeperateChainingAlternate<Key, Value> extends SeperateChainingHashST<Key, Value> {

    int N;
    int M;
    Node[] list = (Node[]) new Object[M]; //  classcast exception

    class Node {
        Node next;
        Key key;
        Value value;
        int n;

        public Node(Key k, Value v, Node next) {
            this.key = k;
            this.value = v;
            this.next = next;
        }
        ......
    }

Please advice me on how to get around this. Im a generics noob

Ravi
  • 133
  • 10

2 Answers2

4

You are casting an Object[] to a Node[]:

Node[] list = (Node[]) new Object[M]; //  classcast exception

The straightforward solution is to just create a Node[] instead:

Node[] list = new Node[M];

However, this fails due to the reason explained here:

Cannot create a generic array of TWTestCase.ModdedSeperateChainingAlternate.Node

So, to achieve your goal, you need to use some Collection instead, preferably a List:

List<Node> list = new ArrayList<Node>(M);

And while you are at it, instance variables should be camel case according to Java standards:

int m;

And further, int m will have the default integer value, which is 0. In other words you will create a zero-length array. Make sure the varaible is initialized (e.g. int i = 5).

As for the generics part, Node derives its types from ModdedSeperateChainingAlternate<Key, Value>. You can read more about generics here.

Community
  • 1
  • 1
Magnilex
  • 10,219
  • 8
  • 49
  • 72
  • Im getting Error:(32, 23) java: generic array creation – Ravi Mar 06 '15 at 11:50
  • @Ravi Wow, I didn't think about that. I have updated my answer with a suggestion to use a `List` instead, and explained the behaviour. – Magnilex Mar 06 '15 at 11:59
1

Node is a non-static nested class. That means it is within the scope of the type parameter of the outer class, and is effectively "parameterized" by that type parameter even though it is not directly on Node.

When you write a bare Node inside ModdedSeperateChainingAlternate, it implicitly means ModdedSeperateChainingAlternate<Key, Value>.Node, which is a parameterized type. You cannot create an array of a parameterized type, e.g. You cannot do new ArrayList<String>[M]; for the same reason, you cannot do new Node[M] (which is equivalent to new ModdedSeperateChainingAlternate<Key, Value>.Node[M]).

Instead, you can do either:

  • create an array of the raw type, like new ArrayList[M]. But how do you write the raw type in this case? It is not Node as we have seen. Instead, you have to explicitly qualify it with the raw outer type:

    Node[] list = new ModdedSeperateChainingAlternate.Node[M];
    
  • or, create an array of the type parameterized with all wildcards, like new ArrayList<?>[M]. In this case, it would be:

    Node[] list = (Node[])new ModdedSeperateChainingAlternate<?, ?>.Node[M];
    
newacct
  • 110,405
  • 27
  • 152
  • 217