泛型类中的静态最终变量导致未经检查的&原型警告

时间:2012-08-16 12:35:10

标签: java generics

在泛型类中使用静态最终变量是一个设计缺陷吗?考虑下面的类,所有对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
    ....
}

3 个答案:

答案 0 :(得分: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的同类树。但是SOIL的一个子树是整数树,而另一个子树是字符串树,因此SOIL想要成为异构树。因此,对于任何SOILNode<E>都不能是E

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

您可以考虑将SOIL设为Set<Node<?>>,而不是让它成为所有词根的父级。你可以把它变成某个地方的静态字段,但把它变成私有的。

答案 1 :(得分:1)

拥有静态最终变量不是设计缺陷。出现警告是因为您在未提供类型参数的情况下声明泛型类型的实例:

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

当编译器期望类似的东西时:

public static final Node<SomeType> SOIL = new Node<SomeType>(null, null);

答案 2 :(得分:0)

您可以使用它来避免抑制警告并且效果很好:

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变量的默认值,即有效Java编程中的NULL对象