Ok so I have a Node in a tree which potentially has a parent (also a Node) and some children (also Nodes).
What I wanted to do with Java’s generics is to allow passing in the type of List the child Nodes would be stored in as well as the data the Node would hold. So I wrote the following class which the compiler seemed happy with.
public class Node<T extends List<Node<T, U>>, U>
{
public Node<T, U> parent;
public T children;
public U data;
private Class<T> tClass;
public Node(Class<T> tClass) throws InstantiationException, IllegalAccessException
{
this.tClass = tClass;
this.children = this.tClass.newInstance();
}
}
The problem was when I tried to initialise a Node.
Node<ArrayList, NodeData> node = new Node(ArrayList.class);
The compiler complains because of a Bound mismatch on the ArrayList. I tried to fix it with the following attempts:
Node<ArrayList<Node>, NodeData> node = new Node(ArrayList.class);
Node<ArrayList<Node<ArrayList, NodeData>>, NodeData> node = new Node(ArrayList.class);
Node<ArrayList<Node<ArrayList<Node>, NodeData>>, NodeData> node = new Node(ArrayList.class);
Node<ArrayList<Node<ArrayList<Node<ArrayList, NodeData>, NodeData>>, NodeData> node = new Node(ArrayList.class);
As you can see this will go on forever, I know I could fix this with
public class Node<T extends List<Node>, U>
{
public Node<T, U> parent;
public T children;
public U data;
private Class<T> tClass;
public Node(Class<T> tClass) throws InstantiationException, IllegalAccessException
{
this.tClass = tClass;
this.children = this.tClass.newInstance();
}
}
Which allows me to use:
Node<ArrayList<Node>, NodeData> node = new Node(ArrayList.class);
However when I do something like:
node.children.get(0).children;
The returned type is a List, not an ArrayList which is what I wanted.
Is what I’m trying to do possible? If so perhaps someone could show me where I’m going wrong or if not what’s the best alternative?
Thanks, Richy.
As you discovered, recursive generics become very complicated very quickly. I see two options for you.
1: Remove T and let children be declared a
List<Node<U>>2: Declared Node to be abstract, add a self reference, and define a concrete ArrayList node reference.