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

「入れる」部分について- 問題は、それがそのタイプが extends するあるタイプの値initのマップだと言っていることですが、それが何であるかを言っていないことです。つまり、合法的にエントリを入れることはできません。本当にそれを - に変更する必要があります。これは、サブクラスではまったく問題なく、以下の反復コードでも問題ありません。DrawnMap<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 に答える