2016-07-05 49 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>