迭代java中的泛型hashmap

时间:2013-08-21 05:46:42

标签: java generics iterator hashmap

我在抽象类中绘制了这个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而不是我可以编译所有内容,但是当我将子类的实例添加到哈希表时,迭代器不会检测到它们。

1 个答案:

答案 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
}
相关问题