2009-11-20 871 views
13

下面給我一個錯誤信息:Java泛型:compareTo和「capture#1 of?」

public static List<Comparable<?>> merge(Set<List<Comparable<?>>> lists) { 
    List<Comparable<?>> result = new LinkedList<Comparable<?>>(); 
    HashBiMap<List<Comparable<?>>, Integer> location = HashBiMap.create(); 

    int totalSize; 
    for (List<Comparable<?>> l : lists) { 
     location.put(l, 0); 
     totalSize += l.size(); 
    } 

    boolean first; 
    List<Comparable<?>> lowest; //the list with the lowest item to add 
    int index; 

    while (result.size() < totalSize) { 
     first = true; 

     for (List<Comparable<?>> l : lists) { 
      if (! l.isEmpty()) { 
       if (first) { 
        lowest = l; 
       } 
       else if (l.get(location.get(l)).compareTo(lowest.get(location.get(lowest))) <= 0) { //error here 
        lowest = l; 
       } 
      } 
     } 
     index = location.get(lowest); 
     result.add(lowest.get(index)); 
     lowest.remove(index); 
    } 
    return result; 
} 

的錯誤是:

The method compareTo(capture#1-of ?) in the type Comparable<capture#1-of ?> is not applicable for the arguments (Comparable<capture#2-of ?>) 

這是怎麼回事?我做了所有類型的東西Comparable,所以我可以撥打.compareTo並對此列表進行排序。我是否正確使用泛型?

+0

其中其中一些需要是,但我沒有時間將這一分類排列成答案。如果沒有其他人,我會晚點回來。 – bmargulies 2009-11-20 15:05:47

回答

20

List<?>意思是「任何東西的列表」,因此兩個這種類型的對象是不一樣的:一個可能是String的列表,另一個列表是BigDecimal。顯然,這些不一樣。

List<T>的意思是「任何東西的列表,但當你再次看到T,它是相同的T」。

在不同的地方你必須告訴編譯器你的意思是相同的類型。試試:

public static <T extends Comparable<? super T>> List<T> merge(Set<List<T>> lists) { 
    List<T> result = new LinkedList<T>(); 
    HashBiMap<List<T>, Integer> location = HashBiMap.create(); 

那麼<T extends Comparable<? super T>> List<T>是什麼意思?第一部分定義了具有以下屬性的類型T:它必須實現接口Comparable<? super T>(或者Comparable<X>,其中X也根據T定義)。

? super T表示Comparable支持的類型必須爲T或其超類型之一。

想象一下這個遺傳:Double extends Integer extends Number。這在Java中是不正確的,但想象一下Double只是Integer加上一個小數部分。在這種情況下,適用於NumberComparable也適用於IntegerDouble,因爲二者均源自Number。因此Comparable<Number>將滿足super部分的TNumber,IntegerDouble

只要每種類型支持接口,它們也滿足聲明的第一部分。這意味着,您可以在Number中傳遞T,並且在列表中有IntegerDouble實例時,生成的代碼也可以使用。如果你IntegerT,你仍然可以使用Double,但Number是不可能的,因爲它不再滿足T extends Comparablesuper部分仍然會工作,雖然)。

下一步是瞭解staticList之間的表達式只是聲明瞭在代碼中稍後使用的T類型的屬性。這樣,你不必一遍又一遍地重複這個長長的聲明。它是方法行爲的一部分(如public),而不是實際代碼的一部分。

+0

我得到'T無法解析爲類型'的錯誤。 – 2009-11-20 15:28:20

+0

我修復了我的答案。此代碼編譯。它在使用時會出錯,刪除''但它應該可以工作。哦,用'ArrayList'替換'LinkedList'。它速度更快,使用的內存更少。 – 2009-11-20 15:39:07

+0

您能否準確解釋'>是什麼意思? – 2009-11-20 21:17:05