由于Java中的协方差规则,我无法创建此通用函数。我知道我可以使用通配符并执行List<? extends/super T>
。我只是看不出它如何适用于这种情况。
如果我想在此处传递dataItems
和Iterable<DataItem>
,我不被允许,因为它们与类型IInterface
不匹配,并且集合不是共变体。
如果我将Map<String, List<IInterface>> target
更改为<? extends IInterface>
,那么由于显而易见的原因,我无法在底部拨打items.add(x);
。
<? super IInterface>
,那么函数很高兴,但我无法使用dataItems
变量调用它,因为DerivedClass
不是IInterface的超类。//DerivedClass implements IInterface which provides getId().
private Map<String, List<DerivedClass>> dataItems;
private Map<String, List<OtherDerivedClass>> otherDataItems;
private void populate(Map<String, List<IInterface>> target,
Iterable<? extends IInterface> source) {
for (final IInterface x : source) {
List<IInterface> items = target.get(x.getId());
if (items == null) target.put(x.getId(),
new ArrayList<IInterface>(){{add(x);}});
else items.add(x);
}
}
问题:我如何修改此功能以使其有效,或者如何更改我的基本设计?
答案 0 :(得分:4)
您是否尝试为整个方法声明泛型类型参数?类似的东西:
private <I extends IInterface> void populate(Map<String, List<I>> target, Iterable<I> source)
答案 1 :(得分:1)
在@fge和@Ray建议的基础上,在您对该功能进行生成后,您可以使用您需要的任何类型调用它,例如
<IInterface>populate(...)
通常,此语法与静态函数一起使用
ClassName.<Type>getWhatever(...);
但没有什么能阻止你非静态地做这件事。
此外,如果您确实对该功能进行了一般化,您需要对其中的所有内容进行生成以反映该限制。意思是这样的
private <I extends IInterface> void populate(Map<String, List<I>> target,
Iterable<I> source) {
for (final I x : source) {
List<I> items = target.get(x.getId());
if (items == null) target.put(x.getId(),
new ArrayList<I>(){{add(x);}});
else items.add(x);
}
}
更多信息:http://java.dzone.com/articles/introduction-generics-java-%E2%80%93