【问题标题】:wildcard in generics behave different in Java 7 and 8泛型中的通配符在 Java 7 和 8 中表现不同
【发布时间】:2016-07-05 10:15:34
【问题描述】:

我的这段代码在编译为 Java 7(Eclipse 编译器)时编译良好,但在我将项目设置设置为 Java 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 是原始类型。对泛型 Comparable 的引用应该被参数化
  • 第 17 行:类型安全:对 Condition 类型的泛型方法 isInRange(T, T) 的未检查调用 isInRange(Comparable, Comparable)

当我在第 15 行添加 &lt;?&gt; 时,警告消失了,但我在第 17 行收到错误:

绑定不匹配:类型的泛型方法isInRange(T, T) 条件不适用于参数 (可比,可比)。推断的 类型 Comparable 不是 有界参数 >

有谁知道究竟是什么导致了这种不兼容?

PS:我添加了这些丑陋的强制转换以使代码在两个版本的 Java 下都能编译:

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

【问题讨论】:

  • eclipse 编译器在泛型方面存在一些错误,因此您应该使用javac 进行测试。
  • 这与通配符无关,而与bound变量的原始类型有关。在 Java-7 中,这有效地关闭了有关 isInRange 方法调用的所有检查。在 Java-8 中,目标类型仍然检测嵌套调用的无效性,类似于this scenario。我不明白,为什么你认为你的类型转换为原始 Comparator 比原始类型的初始用法更丑陋。当然,第二种类型转换是无意义的,因为bound 已经是原始的Comparable
  • @Kayaman:在这种情况下,Eclipse 完全符合javac
  • 你为什么使用原始类型?不要使用原始类型,除非您必须使用原始类型,因为您正在处理无法更改的旧(预泛型)代码。
  • 好吧,这个示例代码没有可推导出的解决方案。 isInRange 方法不能接受 Comparable&lt;?&gt;,因为该类型与所需的参数类型不兼容。您可以通过合并原始类型来禁止泛型类型检查,但正确的解决方案是首先防止获得Comparable&lt;?&gt;。但是我们无法从您的示例中得出,为什么您有这些不完整的类型……

标签: java generics java-8 java-7


【解决方案1】:

首先,我不是泛型专家,所以我的回答可能不正确。我认为问题在于isInRange 方法的定义方式。

<T extends Comparable<T>>

这是一个递归定义,本身不是问题。查看DoubleLong 等类。我相信由于递归定义的解析方式,方法(isInRange)的类型必须是实现Comparable的类,它使用自己作为Comparable的泛型;例如,class C implements Comparable&lt;C&gt;

【讨论】:

    猜你喜欢
    • 2023-03-04
    • 2015-03-09
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多