Java通用类和通配符 [英] Java generic class and wildcards

查看:51
本文介绍了Java通用类和通配符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在使用Java中的泛型类时遇到了问题.

I've got a problem with generic classes in 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(抽象)的简单类.

ConcreteItem is just a simple class that extends AbstractItem (which is abstract).

所以MyChildClass有一个ConcreteItem,我可以使用:

so MyChildClass have a ConcreteItem and I can use:

MyChildClass child = new MyChildClass();
child.setItem(new ConcreteItem());

// automatic cast due to generic class
ConcreteItem item = child.getItem();

好的,暂时一切都很好.问题出在这里:

Ok, all is fine for the moment. Here is the problem:

现在,我想从集合中提取MyMotherClass的实例并设置其项目(类型未知):

Now I want to extract from a collection an instance of MyMotherClass and set its item (which type is not known):

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是泛型类型,并且我不使用泛型类型.但是我不知道提取的孩子是哪种类型,所以我想使用通配符:

If I do like this, it runs. BUT I have warning because MyMotherClass is a generic type and I don't use the generic type. But I don't know which is the type of my extracted child, so I want to use a wildcard:

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)

And here is the problem: I've got a compilation error which says: The method setItem(capture#1-of ?) in the type MyMotherClass is not applicable for the arguments (AbstractItem)

当我尝试使用继承的通配符时,同样的问题:

and when I try with an inherited wildcard, same problem:

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"));

我该怎么办?

感谢和抱歉我的英语不太流利;)

thanks and sorry for my english which is not very fluent ;)

推荐答案

我可能会丢失一些东西,但是为什么不使用显式类 AbstractItem 而不是泛型在MyMotherClass类中进行以下操作类 C ?

I might be missing something, but why not do the following in your MyMotherClass class, using the explicit class AbstractItem rather than the generic class 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;
    }

}

仅此一项更改就可以让您使用通配符方法:

This change alone would allow you to use your wildcard approach:

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():

Of course, in MyChildClass, you can then override MyMotherClass#getItem() as follows:

@Override
public ConcreteItem getItem() {
    return (ConcreteItem) super.getItem();
}

确保返回正确的类;对 MyMotherClass 的所有子类使用相同的方法,将允许您返回正确的类型.

to make sure that the right class is being returned; this same approach for all subclasses of MyMotherClass would allow you to return the right types.

这篇关于Java通用类和通配符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆