2015-10-19 36 views
2

我正在实现一个通用BST,它不允许重复。我已经创建了一个Node类,它具有以下定义:如何防止将另一个通用类型的节点或原始节点添加到BST?

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>相媲美。这似乎一切OK,直到我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) 

它实际上编译,但它不应该,因为我实例StringBinaryTreeSet S,所以我不应该能够号添加到树。

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

+1

至少,有一个警告。 – Tunaki

+4

Java泛型不能处理rawtypes。永远不要使用rawtypes,你不会有这个问题。使用rawtypes并忽略所有的编译器警告,并没有什么编译器可以做些什么来帮助你 - 其实这就是为什么有rawtype编译器警告...... –

+0

@BoristheSpider我绝不会使用原始类型,但也许这个类的客户会,这就是为什么我问是否有防止这种行为的一种方式... – nbro

回答

0

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

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

由于ApproachingDarknessFish注意到你可以调用它像这样迫使javac如果使用RAW类型失败:

javac -Xlint:rawtypes -Werror .... 
相关问题