3

我的抽象类 Drawn 中有这个哈希图,我的目的是用扩展 Drawn 的每个类的每个实例来填充它。我像这样初始化地图:

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

4

1 回答 1

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
}
于 2013-08-21T05:47:51.757 回答