2016-03-03 88 views
3

我正在與TreeSet一起工作,發現ClassCastException,同時調用TreeSet#add()方法。爲什麼TreeSet聲明TreeSet <E>而不是TreeSet <E extends Comparable <E>>

代碼:

public class Testing { 
    public static void main(String[] args) { 
     TreeSet<Testing> ts = new TreeSet<>(); 
     ts.add(new Testing()); 
    } 
} 

輸出:

Exception in thread "main" java.lang.ClassCastException: Testing cannot be cast to java.lang.Comparable 
    at java.util.TreeMap.compare(TreeMap.java:1290) 
    at java.util.TreeMap.put(TreeMap.java:538) 
    at java.util.TreeSet.add(TreeSet.java:255) 
    at Testing.main(Testing.java:13) 

顯然,這是因爲TreeSet有序集合,它需要Comparable對象爲命令他們,那麼爲什麼不宣佈其鍵入爲

public class TreeSet<E extends Comparable<E>> 

並在編譯期間進行檢查,而不是在運行時拋出異常?

回答

7

一個TreeSet的元素沒有實現Comparable,因爲你可以通過一個ComparatorTreeSet之一「,以強制排序爲不執行Comparable(元素或爲做單元S構造如果要使用除Comparable定義的自然順序以外的順序,請執行Comparable)。

+2

我想我問得太快,沒有通過整個API文檔...謝謝... :) – Codebender

0

它的實施方式,您可以訂購無法自行決定的商品,如果訂購的商品應該比「其他」商品更高或更低。

舉一個真實的例子:你有一個選美比賽。如果你問其中一個女孩是否比她旁邊的女孩美麗,她會說是。你不能僅僅通過詢問他們來訂購它們。所以你需要別人來負責訂購,比較器。

這使您可以訂購無法與其他物品進行比較的物品。

1

正如在其他答案中提到的,如果指定了自定義Comparator,那麼TreeSet鍵可能不是Comparable。它仍然可以強制編譯時檢查你的情況。假設我們做默認的構造私人和提供靜態工廠方法代替:

public class TreeSet<E> { 
    private TreeSet() {...} 

    public static <E extend Comparable<? super E>> TreeSet<E> newSet() { 
     return new TreeSet<>(); 
    } 
} 

這樣,你將被迫使用TreeSet.newSet()和編譯時的類型檢查會,如果你把它分配給TreeSet<Testing>Testing失敗不可比。爲什麼沒有完成?因爲泛型只出現在Java 1.5中,而在Java 1.2中出現TreeSet,這是不是一個問題。現在我們必須處理向後兼容性。

相關問題