2016-07-05 50 views
4

我有這樣的代碼時,如Java 7(Eclipse的編譯器)編譯它編譯罰款,但是當我設置的項目設置爲Java 8失敗:通配符泛型在Java 7中的表現不同,8

package scratch; 

class Param<T extends Comparable<T>> { 
    public Comparable<?> get() { 
    return null; 
    } 
} 

public class Condition<T extends Comparable<T>> { 
    public static <T extends Comparable<T>> Condition<T> isInRange(T lower, T upper) { 
    return null; 
    } 

    public void foo() { 
    Comparable bound = null;     // Line 15 
    Param<?> param = new Param<Double>(); 
    Condition.isInRange(param.get(), bound); // Line 17 
    } 
} 

在Java 7,我收到以下警告:

  • 第15行:Comparable是原始類型。引用泛型類型可比應該是參數
  • 17行:類型安全:類型條件的一般方法isInRange(T,T)的未選中調用isInRange(可比,可比)

當我行添加<?> 15,報警消失了,後來我在第17行出現錯誤:

綁定不匹配: 類型條件的一般方法isInRange(T,T)是不適用的參數 (可比,可比)。推斷 類型可比不是一個有效的替代品 界參數>

有誰知道究竟是什麼原因導致這種incompability?

PS:我添加了這些醜陋蒙上使代碼的Java的兩個版本下進行編譯:

Condition.isInRange((Comparable)param.get(), (Comparable) bound); 
+2

eclipse編譯器在泛型方面有一些缺陷,所以你應該用'javac'進行測試。 – Kayaman

+3

這與通配符無關,但與「綁定」變量的* raw類型*無關。在Java-7中,這有效地關閉了所有關於「isInRange」方法調用的檢查。在Java-8中,目標類型仍然檢測到嵌套調用的無效,類似於[此場景](http://stackoverflow.com/a/26285613/2711488)。我不明白,爲什麼你認爲你的類型轉換爲原始的「比較器」比原始類型的初始使用更醜陋。當然,第二種類型轉換是無意義的,因爲「綁定」已經是一個原始的「可比較」了。 – Holger

+2

@Kayaman:在這種情況下,Eclipse完全符合'javac'。 – Holger

回答

0

首先,我不是專家,對仿製藥,所以我的答案可能是不正確的。我相信這個問題是isInRange方法的定義方式。

<T extends Comparable<T>> 

這是一個遞歸定義,它本身不是問題。看看類似Double,Long。我相信由於遞歸定義的解析方式,該方法的類型(isInRange)必須是實現了Comparable的類,該類使用自身作爲Comparable的通用類;例如,class C implements Comparable<C>