Eclipse Java 编译器推断出错误的泛型类型?
Eclipse Java compiler infers the wrong generic type?
我想知道这是 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)
调用,出现错误“类型不匹配:无法从 Collection 转换为 Set”。
getCollection(HashSet::new)
调用对任何编译器来说都不是问题。
如果我应用建议的 quickfix 并向 HashSet<Object>
插入强制转换,我会收到来自 ECJ 的不同错误:“类型推断期间检测到问题:调用 getCollection2 时出现未知错误(GenericsTest.CollectionSupplier<对象,集合>)"
这里有很多类似的问题和 bugs.eclipse.org 处的错误,但大多数示例似乎都涉及 ?
。
请向 Eclipse JDT 报告您遇到的转换问题。
作为变通方法,您可以给 Eclipse 编译器一个提示,如下所示:
Set<Object> set2 = getCollection2((CollectionSupplier<Object, Set<Object>>) HashSet::new);
编译器的棘手部分是检查 getCollection2
return 是否与 Set<Object>
兼容。但要做到这一点,必须知道 HashSet::new
的类型参数,这是由 Set<Object>
确定的(在这种情况下,HashSet::new
创建了 HashSet<Object>
).因此,必须从相反的方向确定类型参数,而不是检查 return 类型是否与需要类型参数的声明类型兼容。
看来,Eclipse 无法计算HashSet::new
的类型参数。 ObjectHashSet::new
与 static class ObjectHashSet extends HashSet<Object> {}
有效。 GenericsTest::newObjectHashSet
和 static Set<Object> newObjectHashSet() { return new HashSet<Object>(); }
也可以工作,但是静态 <T> Set<T> newObjectHashSet() { return new HashSet<T>(); }
.
会失败
我想知道这是 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)
调用,出现错误“类型不匹配:无法从 Collection 转换为 Set”。
getCollection(HashSet::new)
调用对任何编译器来说都不是问题。
如果我应用建议的 quickfix 并向 HashSet<Object>
插入强制转换,我会收到来自 ECJ 的不同错误:“类型推断期间检测到问题:调用 getCollection2 时出现未知错误(GenericsTest.CollectionSupplier<对象,集合>)"
这里有很多类似的问题和 bugs.eclipse.org 处的错误,但大多数示例似乎都涉及 ?
。
请向 Eclipse JDT 报告您遇到的转换问题。
作为变通方法,您可以给 Eclipse 编译器一个提示,如下所示:
Set<Object> set2 = getCollection2((CollectionSupplier<Object, Set<Object>>) HashSet::new);
编译器的棘手部分是检查 getCollection2
return 是否与 Set<Object>
兼容。但要做到这一点,必须知道 HashSet::new
的类型参数,这是由 Set<Object>
确定的(在这种情况下,HashSet::new
创建了 HashSet<Object>
).因此,必须从相反的方向确定类型参数,而不是检查 return 类型是否与需要类型参数的声明类型兼容。
看来,Eclipse 无法计算HashSet::new
的类型参数。 ObjectHashSet::new
与 static class ObjectHashSet extends HashSet<Object> {}
有效。 GenericsTest::newObjectHashSet
和 static Set<Object> newObjectHashSet() { return new HashSet<Object>(); }
也可以工作,但是静态 <T> Set<T> newObjectHashSet() { return new HashSet<T>(); }
.