泛型与功能相似方法的Eclipse错误

时间:2015-09-23 02:36:46

标签: java generics

我有一个Foo<T extends Foo<T>>抽象类。我想基于其父类存储其实现的实例,因此我将它们存储在映射中private static final Map<Class<? extends Foo<?>>, Foo<?>> FOOS = new HashMap<>();要添加到此映射,使用父类调用方法,然后通过反射初始化它。

public static Foo<?> addFoo(Class<? extends Foo<?>> foo) throws InstantiationException, IllegalAccessException {
    return Optional.ofNullable(Foo.FOOS.get(foo)).orElse(Optional.ofNullable(Foo.FOOS.put(foo, foo.newInstance())).orElse(Foo.FOOS.get(foo)));
}

但是这会在Eclipse中产生错误:The method orElse(Foo<capture#25-of ?>) in the type Optional<Foo<capture#25-of ?>> is not applicable for the arguments (Foo<capture#29-of ?>)

然而,这种功能相似的方法不会产生错误。

public static Foo<?> addFoo(Class<? extends Foo<?>> foo) throws InstantiationException, IllegalAccessException {
    Optional<Foo<?>> possibleFoo = Optional.ofNullable(Foo.FOOS.get(foo));
    if(possibleFoo.isPresent()) {
        return possibleFoo.get();
    }
    //The set to possibeFoo with an Optional is not needed, but this is for demonstration purposes
    possibleFoo = Optional.ofNullable(Foo.FOOS.put(foo, foo.newInstance()));
    return Foo.FOOS.get(foo);
}

为什么第一个发出错误但第二个没有,即使它在功能上相似?

1 个答案:

答案 0 :(得分:3)

这是一个产生同样问题的简单示例。

static void example(List<?> list1, List<?> list2) {
    Optional.of(list1).orElse(list2);                // compile error
}

这看起来应该有效。 Optional.of(list1)Optional<List<?>>,因此方法orElse应该适用?

这里的问题是抓取工作的方式。假设list1List<String>。然后我们希望Optional.of(list1)成为Optional<List<String>>。另一方面,如果list1List<Integer>,我们希望Optional.of(list1)Optional<List<Integer>>。因此,编译器不会将Optional.of(list1)的类型视为Optional<List<?>>,而是将Optional<List<X>>视为某种未知类型X

由于类型X未知且list2的项目类型未知,因此可能不匹配。

你可以通过告诉编译器确实希望类型为Optional<List<?>>来解决这个问题:

Optional.<List<?>>of(list1).orElse(list2);   // compiles fine.

你的例子基本相同。你可以像这样编译它。

return Optional.<Foo<?>>ofNullable(FOOS.get(foo))
    .orElse(Optional.<Foo<?>>ofNullable(FOOS.put(foo, foo.newInstance()))
    .orElse(FOOS.get(foo)));

一般来说,如果你在编写涉及通配符和泛型类型的长行代码时遇到问题,我认为将它分解成几行是个好主意,声明一些表达式的类型方式(就像你在第二个例子中所做的那样)。