3

在泛型类中有一个静态最终变量是设计缺陷吗?考虑下面的类,所有引用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<?>or之类的东西Node<Object>。您不能使用通配符类型参数实例化对象,因此您可以做的最好的事情是这样的:

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

(如果您使用 Java 7 菱形构造,无论如何new Node<>(...)它最终都会在这种情况下使用。)Object

问题是,这仍然行不通。Node<E>类型被定义为E的同构树。但是其中一个子SOIL树是Integers树,另一个子树是Strings树,所以SOIL想要成为异构树。因此,SOIL不能是 a Node<E>for any E

至少,不是以类型安全的方式。您可以编写代码来执行此操作,但您必须添加一些强制转换,并且您会收到未经检查的警告。这些警告会告诉您这种方法不起作用。例如,考虑一些采用 aNode<E>并对其所有兄弟(即其父级的其他子级)进行操作的代码。一些需要 a 的代码Node<Integer>可以调用它并以一堆实例结束Node<String>并开始抛出ClassCastExceptions.

您可能会考虑制作SOILaSet<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 回答