2015-10-19 34 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 .... 
相關問題