3

ジェネリック クラスに static final 変数を持つことは設計上の欠陥ですか? 以下のクラスを検討してください。すべての参照でNode.SOIL警告が発生します。この問題を解決するための良い方法は何ですか?

public class Node<E> {

    private static int nodeCounter = 0;

    @SuppressWarnings({ "unchecked", "rawtypes" })  
    public static final Node SOIL = new Node(null, null); // <-- HERE
    public static void resetSOIL(){
        SOIL.children = null; // <-- HERE
    }

    private Node<E> parent;
    private Set<Node<E>> children;

    protected Set<Node<E>> isomorphs;
    private E data;
    private int id;

    public Node(Node<E> parent, E data){
        this.parent = parent;
        this.data = data;
        this.id = ++nodeCounter;

    }

    public boolean isRoot(){
        return (this.getParent() == SOIL);
    }

    // utility methods
    ....
}
4

3 に答える 3

2

Node<E>E のツリー内のノードを表す型を定義しました。たとえば、Node<Integer>は整数のツリーのNode<String>ノードであり、文字列のツリーのノードです。

SOILここで、さまざまな種類のこれらのさまざまな木のすべての根を含む変数が必要です (へへ、、わかりました)。今のところ、静的フィールドの問題は脇に置いておいてください。のクラスは何SOILですか?SOILつまり、インスタンスをどのように宣言して作成するのでしょうか?

Node</*something1*/> SOIL = new Node</*something2*/>(null, null);

SOILは の子を持つため、またはのようなものでなければなりませNode<Integer>ん。ワイルドカード型の引数を使用してオブジェクトをインスタンス化することはできないため、できる最善の方法は次のようなものです。Node<String>Node<?>Node<Object>

Node<?> SOIL = new Node<Object>(null, null);

(Java 7 ダイヤモンド コンストラクトnew Node<>(...)を使用するObjectと、この場合は最終的に使用されます。)

問題は、これがまだ機能しないことです。Node<E>型が定義される方法は、E の同種ツリーとして定義されます。しかし、 の 1 つのサブツリーSOILは整数のツリーであり、別のサブツリーは文字列のツリーであるため、異種SOILツリーになりたいと考えています。したがって、for anyにすることはできません。SOILNode<E>E

少なくとも、タイプセーフな方法ではありません。これを行うコードを作成することもできますが、いくつかのキャストを追加する必要があり、チェックされていない警告が表示されます。これらの警告は、このアプローチが機能していないことを示しています。たとえば、 を取り、Node<E>そのすべての兄弟 (つまり、親の他の子) を操作するコードを考えてみましょう。を受け取った一部のコードは、Node<Integer>これを呼び出して、一連のインスタンスで終了し、 をNode<String>スローし始める可能性がありますClassCastExceptions

を作成し、それをすべてのルートの親にしないことを検討するかもしれませんSOILSet<Node<?>>どこかで静的フィールドにすることもできますが、プライベートにします。

于 2012-08-18T07:03:22.630 に答える
1

静的な最終変数を持つことは設計上の欠陥ではありません。型パラメーターを指定せずにジェネリック型のインスタンスを宣言しているため、警告が表示されます。

public static final Node SOIL = new Node(null, null); // <-- HERE

コンパイラが次のようなものを期待している場合:

public static final Node<SomeType> SOIL = new Node<SomeType>(null, null);
于 2012-08-16T12:42:47.597 に答える
0

これを使用すると、suppressWarnings を回避でき、うまく機能します。

private static final Node<Object> SOIL = new Node<Object>(null, null);

他の質問に答えるには:

Is it a design flaw to have a static final variable in a generic class?

いいえ、それは Node 型の null 変数 (Effective Java Programming の NULL オブジェクトとも呼ばれる) のデフォルトとして使用するのが一般的な良い方法です。

于 2012-08-16T12:47:40.800 に答える