2013-08-21 41 views
3

我在抽象类Drawn中有这个hashmap,我的意图是用每个扩展Drawn的类的每个实例来填充它。我初始化地图像这样:在java中对一个通用的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()代码有编译时错误。 但是,如果我将类型参数更改为Drawn而不是I可以让所有东西都能编译,但是当我将子类的实例添加到散列表时,它们不会被迭代器检测到。

+1

请注意,您在实例的原始类型的HashMap。这将是你未经检查的转换警告。你应该把你的RHS改为'new HashMap <>();',如果已经在Java 7上了。 –

回答

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 
} 
+0

错误似乎是'put'方法。 Map中的值类型是?延伸Drawn',这是错误。他不能添加任何东西。 –

+0

@RohitJain:是的,我现在已经谈到了这个部分。但迭代的一部分也被完全打破了写在问题中。 –

+0

是的,我注意到了。我即将发布答案,但你已经做到了。 :) –