【发布时间】: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 行添加 <?> 时,警告消失了,但我在第 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<?>,因为该类型与所需的参数类型不兼容。您可以通过合并原始类型来禁止泛型类型检查,但正确的解决方案是首先防止获得Comparable<?>。但是我们无法从您的示例中得出,为什么您有这些不完整的类型……
标签: java generics java-8 java-7