19

パラメータ化されたタイプがわからないマップのエントリセットを反復処理する必要があります。

そのようなエントリセットを反復処理するとき、なぜこれがコンパイルされないのですか?

public void myMethod(Map anyMap) {
    for(Entry entry : anyMap.entrySet()) {
        ...
    }
}

しかし、このコンパイル:

public void myMethod(Map anyMap) {
    Set<Entry> entries = anyMap.entrySet();
    for(Entry entry : entries) {
        ...
    }
}

これもコンパイルされます(マップのタイプがわからないため、これを使用できません):

public void myMethod(Map<String, String> stringMap) {
    for(Entry<String,String> entry : stringMap.entrySet()) {
        ...
    }
}
4

6 に答える 6

24

最初のエラーは次のとおりです。

Type mismatch: cannot convert from element type Object to Map.Entry

これは、コンパイラが FOR-IN ループを変換するためです。

for (Entry entry : anyMap.entrySet()) {
}

に:

for (Iterator i = anyMap.entrySet().iterator(); i.hasNext();) {
    Entry e = i.next(); // not allowed
}

2番目の例は機能しますが、不正行為によってのみ機能します! Set に戻る ために未チェックのキャストを行っていますSet<Entry>

Set<Entry> entries = anyMap.entrySet(); // you get a compiler warning here
for (Entry entry : entries) {
}

なる:

Set<Entry> entries = anyMap.entrySet();
for (Iterator<Entry> i = entries.iterator(); i.hasNext(); ) {
    Entry e = (Entry) i.next(); // allowed
}

アップデート

コメントで述べたように、両方の例で型情報が失われています: コンパイラの生の型消去規則のためです。

下位互換性を提供するために、raw 型インスタンスのすべてのメソッドは、消去された対応するメソッドに置き換えられます。したがって、 yourMapは raw タイプであるため、すべて消去されます。そのSet<Map.Entry<K, V>> entrySet();メソッドを含む: 生の型インスタンスは、消去されたバージョンを使用することを余儀なくされます: Set entrySet()

于 2013-02-18T10:19:29.157 に答える
7

これは、生の型 Map を使用しているためです。したがって、 map.entrySet() は、パラメーター化されていない Set を取得します。これにより、反復時に Entry ではなく Object が生成されます。

シンプルで洗練された解決策は、Map<?,?> を使用することです。これにより、ANY Map を渡すことができますが、一方で、map.entrySet() に強制的に Set<Entry> の戻り値を持たせます。

public void test(Map<?,?> map) {        
    for(Entry e : map.entrySet()){
        Object key = e.getKey();
        Object value = e.getValue();
    }       
}
于 2013-02-18T10:40:49.430 に答える
2

最初の例では、map.entrySet() は Set を返します。ループで反復するときは、Iterator を使用します。セット コンテンツ タイプに関する情報がないため、Java は Object を Object として使用し、Object は基本型であり、コンパイラは Object を Entry に変換できないことを通知します。

Set<Map.Entry<K, V>> entrySet();

raw マップ タイプを使用すると、entrySet はタイプ情報なしで Set のみを返します。

2 番目の例では、手動で Set を Set<Entry> に変換します (警告あり)。これで、Java はその中身を認識します。だからあなたは繰り返すことができます。

最後の例では、マップ タイプがわかっているため、entrySet は正しい型指定された Set を返し、型規則なしで反復できます。

于 2013-02-18T10:20:05.097 に答える
1

変数が存在しないため、最初のコード スニペットはコンパイルされmapません。パラメータを呼び出しましたanyMapが、としてアクセスしようとしました。それをmap修正すると、コードは rawtypes 警告を除いてコンパイルされます

于 2013-02-18T10:06:16.967 に答える