2

我想知道这是 ECJ 中的错误还是对 JLS 的有效解释。

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Supplier;

public class GenericsTest {
    public void testInference() {
        Set<Object> set1 = getCollection(HashSet::new);
        Set<Object> set2 = getCollection2(HashSet::new);
    }

    public static <E, C extends Collection<E>> C getCollection(Supplier<C> collectionSupplier) {
        return collectionSupplier.get();
    }

    public static <E, C extends Collection<E>> C getCollection2(CollectionSupplier<E, C> collectionSupplier) {
        return collectionSupplier.get();
    }

    public interface CollectionSupplier<E, C extends Collection<E>> {
        C get();
    }
}

Javac (11.0.11) 编译一切(我会说是正确的)。

ECJ (4.20.0) 无法编译getCollection2(HashSet::new)调用并出现错误“类型不匹配:无法从集合转换为集合”。

对于getCollection(HashSet::new)任何编译器来说,调用都不是问题。

如果我应用建议的快速修复并插入强制转换HashSet<Object>,我会收到来自 ECJ 的不同错误:“在类型推断期间检测到问题:调用 getCollection2(GenericsTest.CollectionSupplier<Object,Collection>) 时出现未知错误”

这里有很多类似的问题和bugs.eclipse.org上的错误,但大多数示例似乎都涉及?

4

1 回答 1

1

请将您在演员阵容中遇到的问题报告给 Eclipse JDT。

作为一种解决方法,您可以给 Eclipse 编译器一个提示,如下所示:

Set<Object> set2 = getCollection2((CollectionSupplier<Object, Set<Object>>) HashSet::new);

编译器的棘手部分是检查getCollection2返回的内容是否与Set<Object>. 但为了能够做到这一点,HashSet::new必须知道 的类型参数,这由Set<Object>(在这种情况下,HashSet::new创建 的实例HashSet<Object>)确定。因此,类型参数必须从相反的方向确定,而不是检查返回类型是否与需要类型参数的声明类型兼容。

看来,Eclipse 无法计算HashSet::new. ObjectHashSet::newstatic class ObjectHashSet extends HashSet<Object> {}作品。GenericsTest::newObjectHashSetwithstatic Set<Object> newObjectHashSet() { return new HashSet<Object>(); }也可以,但使用 static 失败<T> Set<T> newObjectHashSet() { return new HashSet<T>(); }

于 2021-08-04T14:56:15.347 回答