我在抽象类中绘制了这个hashmap,我的目的是用每个延伸绘制的类的每个实例填充它。我像这样初始化地图:
public static HashMap<Integer, ? extends Drawn> drawns = new HashMap();
我尝试将元素添加到哈希表中,如下所示:
//this code is in the abstract class Drawn()
public void init(){
idCount++;
setID(idCount);
drawns.put(idCount,this);
}
然后我尝试迭代:
for(<Integer, ? extends Drawn> E : Drawn.drawns.values()) {
E.draw();
}
迭代器和init()代码都有编译时错误。 但是,如果我将类型参数更改为Drawing而不是我可以编译所有内容,但是当我将子类的实例添加到哈希表时,迭代器不会检测到它们。
答案 0 :(得分:5)
对于init
中的“推送”部分 - 问题在于您说它是某种类型的值的地图,其中该类型扩展Drawn
,但你不是说它是什么。这意味着你不能合法地输入任何条目。你真的需要将它改为Map<Integer, Drawn>
- 这对于子类应该是绝对正确的,下面的迭代代码仍然是没事。
你不能做你想做的事情的原因是类型系统试图阻止这类问题:
Map<Integer, String> stringMap = new HashMap<Integer, String>();
Map<Integer, ? extends Object> objectMap = stringMap; // This is fine
objectMap.put(10, new Object()); // This *mustn't* be valid...
String value = stringMap.get(10); // Or this would be dangerous
当你从地图中获取一个值时,你只会知道它是一个Drawn
引用 - 如果你想使用任何子类特定的方法,你需要转换为正确的类型。如果你想拥有一个可以有多种不同价值的地图,这是不可避免的。
当你在值上进行迭代时,你可以使用:
for (Drawn drawn : Drawn.drawns.values()) {
drawn.draw();
}
或者如果您还需要密钥:
// Or Map.Entry<Integer, Drawn> after the earlier change
for (Map.Entry<Integer, ? extends Drawn> entry : Drawn.drawns.entrySet()) {
// Use entry.getKey() and entry.getValue() here
}