如我所见,您的代码中有两个错误。首先是相信该类型List<Ref<? extends Thing>>是 的超类型List<Ref<Thing>>。如果我们创建 like 的子Thing类DerivedThing,我们不能将 的实例添加Ref<DerivedThing>到 的列表中List<Ref<Thing>>:
List<Ref<Thing>> refs = new ArrayList<Ref<Thing>>();
refs.add(new Ref<Thing>()); // OK.
refs.add(new Ref<DerivedThing>()); // Error!
但是,如果我们将其替换为List<Ref<? extends Thing>>then 类就没有问题了DerivedThing:
List<Ref<? extends Thing>> refs = new ArrayList<Ref<? extends Thing>>();
refs.add(new Ref<Thing>()); // Still OK.
refs.add(new Ref<DerivedThing>()); // Now OK!
因此,如果编译器允许将 的值作为其参数传递List<Ref<? extends Thing>>给函数List<Ref<? extends Thing>>,这将允许该函数将一些无效项添加到列表中。
第二个错误是认为的基本类型(或擦除类型)<? extends Thing>是SuperThing而不是剩余Thing。在这里,<? extends Thing>指定由组成的类型Thing及其派生类的集合,而不是由及其派生类组成的集合SuperThing。因此,我们可以这样写:
List<Ref<? extends Thing>> refs = new ArrayList<Ref<? extends Thing>>();
refs.add(new Ref<Thing>());
List<Thing> objectList = refsToObjects(refs);
或者,SuperThing作为擦除类型:
List<Ref<? extends SuperThing>> refs = new ArrayList<Ref<? extends SuperThing>>();
refs.add(new Ref<Thing>());
List<SuperThing> objectList = refsToObjects(refs);
但不是两者的组合,因为List<SuperThing>它不是一个超类,List<Thing>. 请注意我们仍然可以将 a 添加Ref<Thing>到 a List<Ref<? extends SuperThing>>。因此,如果您想保留作为起点,请使用上述解决方案之一或使用wrm 的解决方案。List<Ref<Thing>>
就个人而言,我更愿意充分利用多态性,并始终引用 a 中的所有内容SuperThing;即使在创建Thing或Ref<Thing>对象时。例如,如果我们T向 的构造函数添加一个类型的参数Ref():
List<Ref<SuperThing>> refs = new ArrayList<Ref<SuperThing>>();
refs.add(new Ref<SuperThing>(new Thing()));
List<SuperThing> objectList = refsToObjects(refs);
请注意,我们现在将一个类型的对象传递给的构造函数中的一个类型Thing的引用。通过使用层次结构的超类作为所有派生对象的引用,所有编码变得更加简单。当您选择主要只通过它们的超类查看所有对象时,OOP 工作得非常好并且非常容易,这扩展到了泛型的使用。SuperThingRef()