我对泛型有一些问题,让我解释一下。
我有一个包装LinkedList的类:
public class IdnList<T extends Numerable> extends IdnElement implements List<T> {
private LinkedList<T> linkedList;
@Override
public boolean add(T e){
return linkedList.add(e);
}
//stuff
}
请注意此类T
的通用类型extends
Numerable
接口。
好的,现在在另一个类中,我想调用此方法,如下所示:
if(childToAdd instanceof Numerable)
((IdnList<?>)this).add((Numerable)childToAdd);
但是eclipse说:The method add(capture#1-of ?) in the type IdnList<capture#1-of ?> is not applicable for the arguments (Numerable)
,我真的无法弄清楚它为什么不起作用。为什么我不能在列表中添加Numerable
对象?
我错过了什么?
修改 这是一部经典之作。你问,然后你找到了一个线索。似乎解决方法是:
((IdnList<Numerable>)this).add((Numerable)childToAdd);
但我不知道它有多优雅。我非常感谢您的进一步评论。
答案 0 :(得分:2)
假设您的课程A
和B
都延伸Numerable
。然后有三种有效类型IdnList
:IdnList<A>
,IdnList<B>
和IdnList<Numerable>
。
我希望您同意您不能将任何Numerable
添加到IdnList<A>
。
现在,在这行代码中,编译器如何知道您是否正确匹配了类型?
(IdnList<?>)this).add((Numerable)childToAdd);
它只知道childToAdd
是Numerable
,而this
是某种IdnList
。它不知道是什么类型,因此无法保证类型安全。请记住,泛型类型检查完全在编译时完成,而不是运行时。
我看到变通方法如何允许代码编译,但我不确定它的风险是什么。在我看来,由于泛型类型参数在运行时被擦除,基本上你只是绕过所有类型检查。
答案 1 :(得分:1)
问题在于引用其他类中的IdnList实例。 我在你的代码示例中看不到它,但看起来它没有与之关联的正确类型,特别是当它被强制转换为通配符时。
由于IdnList需要为每个实例设置一个类型(T),因此编译器无法知道您要执行的操作。
如果您对IdnList的引用具有与之关联的正确类型,它将接受T的任何子类,如下所示:
IdnList<Numerable> list = new IdnList<Numerable>();
list.add(new Numerable());
list.add(new AnotherType());
list.add(new YetAnotherType());
(鉴于AnotherType和YetAnotherType是Numerable的子类)
由于您对实例的引用没有设置任何类型,我猜你实际上要做的是:
public class IdnList extends IdnElement implements List<Numerable> {
private LinkedList<Numerable> linkedList;
@Override
public boolean add(Numerable e) {
return linkedList.add(e);
}
}