2013-08-21 73 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

是的,我注意到了。我即將發佈答案,但你已經做到了。 :) –