2011-07-28 12 views
2

私は潜在的に親(ノードも)といくつかの子供(またノード)を持つツリー内のノードを持っています。Javaツリーノード再帰ジェネリック

私がJavaのジェネリックスでやりたいことは、ノードが保持するデータだけでなく、ノードが格納されるリストの型を渡すことです。だから私はコンパイラが満足していたと思う次のクラスを書いた。

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

ノードを初期化しようとしたときに問題が発生しました。

Node<ArrayList, NodeData> node = new Node(ArrayList.class); 

コンパイラは、ArrayListのバウンドの不一致のために不平を言っています。

:私は私は私が使用することができます

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

でこれを修正する可能性が知っている、あなたはこれが永遠に行く見ることができるように

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

:私は次の試みでそれを修正しようとしました

Node<ArrayList<Node>, NodeData> node = new Node(ArrayList.class); 

しかし、私はのような何かをするとき:

node.children.get(0).children; 

返される型は、私が望むArrayListではなくListです。

私がしようとしていることは可能ですか?もしそうなら、誰かが私がどこに間違っているのか、それとも最良の選択肢がないのかを私に見せてくれるでしょうか?

ありがとう、Richy。

+2

"返される型は、リストであり、私が欲しいものではないArrayListです..."なぜこれが問題ですか? 'children'は' ArrayList'ではなく 'List'であると宣言されています。 –

+0

Jimに加えて: 'ArrayList'は' List'ですが、リストが実際にどのように実装されているかは関係ありません。リストであることを知るには十分なはずです – Tedil

+0

リストのタイプを一般的にしないでください。 'List 'を使っても問題ありません。 – starblue

答えて

4

あなたが発見したように、再帰ジェネリックは非常に迅速に非常に複雑になります。私はあなたのための2つのオプションが表示されます。

1:Tを削除し、子どもたちが宣言させList<Node<U>>

2:宣言ノードは、自己参照を追加し、抽象的で、かつ具体的なArrayListのノードの参照を定義します。

abstract class Node<N extends Node<N, T, U>, T extends List<N>, U> 
{ 
    public Node<N, 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(); 
    } 
    { 
     Node<ALNode<Integer>, ArrayList<ALNode<Integer>>, Integer> node = new ALNode<Integer>(); 
     ALNode<Integer> node2 = new ALNode<Integer>(); 
    } 
} 

class ALNode<U> extends Node<ALNode<U>, ArrayList<ALNode<U>>, U> { 

    public ALNode() throws InstantiationException, 
      IllegalAccessException { 
     super((Class) ArrayList.class); 
    } 

}