以下是我正在处理的一些代码示例:
public interface FooMaker<T extends Enum<T> & FooType>
{
public List<Foo<T>> getFoos(String bar);
}
让我们进一步假设FooMaker会有许多不同的具体实现。所以我写了一些代码来使用FooMakers。
FooMaker<?> maker = Foos.getRandomMaker();
List<Foo<?>> fooList = maker.getFoos("bar"); //error here!
第二行代码导致问题,eclipse告诉我代码应该是:
FooMaker<?> maker = Foos.getRandomMaker();
List<?> fooList = maker.getFoos("bar");
我无法理解为什么Foo声明作为List中的参数化类型必须消失才能使返回类型正确。
有什么想法吗?
答案 0 :(得分:1)
通常的:
class Bar {}
class Baz {}
FooMaker<?> maker = new FooMaker<Bar>();
List<Foo<?>> fooList = maker.getFoos("bar"); //error here!
fooList.add(new Foo<Baz>()); //cock-up here!
答案 1 :(得分:1)
请改为尝试:
List<? extends Foo<? extends Enum<?>>> fooList = maker.getFoos("bar");
问题是,如果允许这样做:
List<Foo<?>> fooList = maker.getFoos("bar");
然后,通过扩展,你也可以逃脱这个:
Foo<?> foo1 = new Foo<String>();
Foo<?> foo2 = new Foo<Integer>();
fooList.add(foo1);
fooList.add(foo2);
哪会使返回列表的通用合约无效。
为了防止这种情况,java编译器强制返回类型是基于通配符的,这意味着Foo可以用作返回类型(将元素拉出列表),但是你将无法添加基于通配符的Foo键入您的列表。
答案 2 :(得分:0)
因为您将maker
声明为FooMaker<?>
。如果您知道具体的AwesomeFooMaker
T
返回什么,为什么不将其声明为AwesomeFooMaker
的类型?