2

我正在实现一个通用的 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)

它实际上可以编译,但它不应该,因为我正在实例化BinaryTreeSets String,所以我不应该能够将数字添加到树中。

我做错了什么,为什么?在这些情况下,我怎样才能让它不编译?

4

1 回答 1

0

没有办法阻止这种情况,因为 Java 在运行时不保留泛型类型信息。当程序执行时value是一个Object,因此可以同时保存一个Integer和一个String

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

正如 ApproachingDarknessFish 所指出javac的,如果您使用原始类型,则可以通过如下方式调用它来强制失败:

javac -Xlint:rawtypes -Werror ....
于 2016-04-19T05:26:14.563 回答