Java 类型推断 : reference is ambiguous in Java 8, 但不是 Java 7

标签 java generics compiler-errors java-8 type-inference

假设我们有 2 个类(class)。空类Base ,以及此类的子类Derived .

public class Base {}

public class Derived extends Base {}

那么我们在另一个类中有几个方法:

import java.util.Collection

public class Consumer {

    public void test() {
        set(new Derived(), new Consumer().get());
    }

    public <T extends Base> T get() {
        return (T) new Derived();
    }

    public void set(Base i, Derived b) {
        System.out.println("base");
    }

    public void set(Derived d, Collection<? extends Consumer> o) {
        System.out.println("object");
    }

}

这在Java 7中编译并运行成功,但在Java 8中无法编译。错误:

Error:(8, 9) java: reference to set is ambiguous
  both method set(Base,Derived) in Consumer and 
  method set(Derived,java.util.Collection) in Consumer match

为什么在 Java 7 中有效,但在 Java 8 中无效?怎么可能<T extends Base> 曾经匹配 Collection ?

最佳答案

问题在于类型推断已改进。你有一个类似的方法

public <T extends Base> T get() {
    return (T) new Derived();
}

这基本上是说,“调用者可以决定 Base 的子类。我回来了”,这显然是胡说八道。每个编译器都应该给你一个关于你的类型转换的未经检查的警告 (T)在这里。

现在你有一个方法调用:

set(new Derived(), new Consumer().get());

回想一下你的方法 Consumer.get()说“调用者可以决定我返回什么”。因此,假设可能存在扩展 Base 的类型是完全正确的。并实现Collection同时。所以编译器说“我不知道是否调用 set(Base i, Derived b)set(Derived d, Collection<? extends Consumer> o) ”。

您可以通过调用 set(new Derived(), new Consumer().<Derived>get()); 来“修复”它但为了说明您的方法的疯狂,请注意您也可以将其更改为

public <X extends Base&Collection<Consumer>> void test() {
    set(new Derived(), new Consumer().<X>get());
}

现在将调用 set(Derived d, Collection<? extends Consumer> o)没有任何编译器警告。实际的不安全操作发生在 get 内部。方法。

所以正确的解决方法是从 get 中删除类型参数方法并声明它真正返回的内容,Derived .


顺便说一句,让我恼火的是你声称这段代码可以在 Java 7 下编译。它对嵌套方法调用的有限类型推断导致处理 get嵌套调用上下文中的方法,例如返回 Base不能传递给期望 Derived 的方法.因此,尝试使用符合标准的 Java 7 编译器编译此代码也会失败,但原因不同。

关于Java 类型推断 : reference is ambiguous in Java 8, 但不是 Java 7,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28466925/

相关文章:

java - 将一种数据结构与另一种数据结构进行比较,导致运行时间超过 50 分钟

scala - Scala 中如何处理返回泛型类型对象的函数

Swift 4 - 关联类型的子类通用约束

c# - 转发泛型类型定义

java - 在 jframe 上显示列表

java - java.util 中的模块(集合)

java - 无法解决此错误 : Failed to configure a DataSource

c++ - Visual C++ Studio 2010 无故显示生成错误

javascript - React 无法编译 postcss、yamldumper.js

actionscript-3 - 在AS3中将符号添加到阶段出现1046错误