Java泛型类和通配符
作者:互联网
我在java中遇到泛型类的问题.
我有这门课:
public abstract class MyMotherClass<C extends AbstractItem>
{
private C item;
public void setItem(C item)
{
this.item = item;
}
public C getItem()
{
return item;
}
}
这个类的实现可以是:
public class MyChildClass extends MyMotherClass<ConcreteItem>
{
}
ConcreteItem只是一个扩展AbstractItem(它是抽象的)的简单类.
所以MyChildClass有一个ConcreteItem,我可以使用:
MyChildClass child = new MyChildClass();
child.setItem(new ConcreteItem());
// automatic cast due to generic class
ConcreteItem item = child.getItem();
好的,目前一切都很好.这是问题所在:
现在我想从集合中提取MyMotherClass的一个实例并设置它的项目(哪个类型未知):
Map<String, MyMotherClass> myCollection = new HashMap<String, MyMotherClass>();
Map<String, AbstractItem> myItems = new HashMap<String, AbstractItem>();
// fill the 2 collections
...
MyMotherClass child = myCollection.get("key");
child.setItem(myItems.get("key2"));
如果我喜欢这样,它会运行.
但我有警告,因为MyMotherClass是泛型类型,我不使用泛型类型.
但是我不知道我提取的孩子的类型是哪个,所以我想使用通配符:
Map<String, MyMotherClass<?>> myCollection = new HashMap<String, MyMotherClass<?>>();
Map<String, AbstractItem> myItems = new HashMap<String, AbstractItem>();
// fill the 2 collections
...
MyMotherClass<?> child = myCollection.get("key");
child.setItem(myItems.get("key2"));
这是问题:我有一个编译错误,说:
MyMotherClass类型中的方法setItem(capture#1-of?)不适用于参数(AbstractItem)
当我尝试使用继承的通配符时,同样的问题:
Map<String, MyMotherClass<? extends AbstractItem>> myCollection = new HashMap<String, MyMotherClass<? extends AbstractItem>>();
Map<String, AbstractItem> myItems = new HashMap<String, AbstractItem>();
// fill the 2 collections
...
MyMotherClass<? extends AbstractItem> child = myCollection.get("key");
child.setItem(myItems.get("key2"));
我能做什么 ?
谢谢,抱歉我的英语不是很流利;)
解决方法:
我可能会遗漏一些东西,但是为什么不在MyMotherClass类中使用显式类AbstractItem而不是泛型类C来执行以下操作?
public abstract class MyMotherClass<C extends AbstractItem> {
private AbstractItem item;
public void setItem(AbstractItem item) {
this.item = item;
}
public AbstractItem getItem() {
return this.item;
}
}
仅此更改将允许您使用通配符方法:
Map<String, MyMotherClass<?>> myCollection = new HashMap<String, MyMotherClass<?>>();
Map<String, AbstractItem> myItems = new HashMap<String, AbstractItem>();
// fill the 2 collections
MyMotherClass<?> child = myCollection.get("key");
child.setItem(myItems.get("key2"));
没有错误.
当然,在MyChildClass中,您可以覆盖MyMotherClass#getItem(),如下所示:
@Override
public ConcreteItem getItem() {
return (ConcreteItem) super.getItem();
}
确保返回正确的班级;对于MyMotherClass的所有子类,这种相同的方法将允许您返回正确的类型.
标签:java,wildcard,generics,generic-programming 来源: https://codeday.me/bug/20190527/1159846.html