编程语言
首页 > 编程语言> > Java泛型类和通配符

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