Jer*_*nce 4 java generics wildcard generic-programming
我在java中遇到泛型类的问题.
我有这门课:
public abstract class MyMotherClass<C extends AbstractItem>
{
private C item;
public void setItem(C item)
{
this.item = item;
}
public C getItem()
{
return item;
}
}
Run Code Online (Sandbox Code Playgroud)
这个类的实现可以是:
public class MyChildClass extends MyMotherClass<ConcreteItem>
{
}
Run Code Online (Sandbox Code Playgroud)
ConcreteItem只是一个扩展AbstractItem(它是抽象的)的简单类.
所以MyChildClass有一个ConcreteItem,我可以使用:
MyChildClass child = new MyChildClass();
child.setItem(new ConcreteItem());
// automatic cast due to generic class
ConcreteItem item = child.getItem();
Run Code Online (Sandbox Code Playgroud)
好的,目前一切都很好.这是问题所在:
现在我想从集合中提取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"));
Run Code Online (Sandbox Code Playgroud)
如果我喜欢这样,它会运行.但我有警告,因为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"));
Run Code Online (Sandbox Code Playgroud)
这就是问题所在:我遇到了一个编译错误: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"));
Run Code Online (Sandbox Code Playgroud)
我能做什么 ?
谢谢,抱歉我的英语不是很流利;)
对于write操作,您需要一个super通配符.
final Map<String, MyMotherClass<? super AbstractItem>> myCollection =
new HashMap<String, MyMotherClass<? super AbstractItem>>();
final Map<String, AbstractItem> myItems =
new HashMap<String, AbstractItem>();
...
final MyMotherClass<? super AbstractItem> child =
myCollection.get("key");
child.setItem(myItems.get("key2"));
Run Code Online (Sandbox Code Playgroud)
extends通配符用于read操作.
编辑:回应你的评论.
首先,评估您是否真的需要通配符.
如果答案仍然是肯定的,那么您可以将集合初始化为更具体的类型,然后将它们向下转换为有界通配符,例如
final Map<String, MyChildClass> myInitCollection =
new HashMap<String, MyChildClass>();
final Map<String, ConcreteItem> myInitItems =
new HashMap<String, ConcreteItem>();
myInitCollection.put( "key", new MyChildClass( ) );
final MyMotherClass< ConcreteItem> child =
myInitCollection.get("key");
child.setItem(myInitItems.get("key2"));
final Map<String, ? extends MyMotherClass< ? extends AbstractItem >>
myCollection = myInitCollection;
final Map<String, ? extends AbstractItem> myItems = myInitItems;
Run Code Online (Sandbox Code Playgroud)
但是请注意,myCollection仍然无法安全地转换为Map<String, MyMotherClass< ? extends AbstractItem>>.
另外,阅读本文关于有界通配符参数,以及何时避免它们.