如何防止其他泛型节点或原始节点被添加到BST



我正在实现一个通用的BST,它不允许重复。我已经创建了一个Node类,它具有以下定义:

class Node<T extends Comparable<T>> implements Comparable<Node<T>>{
    private T value;
    // other stuff
}
使用

,我基本上希望与某个节点关联的值与相同类型的其他值具有可比性。然后我也有下面的compareTo方法:

@Override
public int compareTo(Node<T> o) {
    return value.compareTo(o.value);
}

现在,在我的BST的实现中,我有一个关于参数接受的问题。BST有以下定义:

public class BinaryTreeSet<T extends Comparable<T>> {
    private Node<T> root;
    // other stuff
}

您可以看到,我要求根的泛型类型与具有相同泛型类型的其他值具有可比性,即T extends Comparable<T>。这似乎都没问题,直到我的add方法的实现,它具有以下签名:

public void add(Node<T> n) {...}

没有什么可疑的(至少对我来说),但是如果我有以下代码:

BinaryTreeSet<String> t = new BinaryTreeSet<>();
t.add(new Node(12));  // Adding a raw Node (whose value is actually an integer)

它实际上编译了,但它不应该编译,因为我正在实例化BinaryTreeSetString s,所以我不应该能够向树中添加数字。

我做错了什么,为什么?在这些情况下,我如何使它不编译?

没有办法防止这种情况,因为Java在运行时不保留泛型类型信息。当程序执行时,valueObject,因此可以同时保存IntegerString

实践中的解决方案是简单地禁止代码中的原始类型。几乎没有理由在现代Java应用程序中使用它们,只有在经过良好测试且可见性受限的库代码中才使用它们。从不应用逻辑。如果您应该使用原始类型,javac已经打印了一个警告,您最好不要忽略它们。

正如ApproachingDarknessFish所指出的,如果你使用原始类型,你可以通过这样调用它来强制javac失败:

javac -Xlint:rawtypes -Werror ....

最新更新