Problema con el conjunto de entradas de java.util.Map

I'm having a strange problem with the following code works.

Map<String, Object> map = new HashMap<String, Object>();

for(Entry<String, Object> entry : map.entrySet()) {
   // 
}

while the code below does not compile.

Map map = new HashMap();

for(Entry entry : map.entrySet()) {  // compile error here
   // 
}

¿Alguna pista?

preguntado el 28 de agosto de 11 a las 03:08

Hm. But Set<Entry> entries = data.entrySet(); for (Entry entry : entries) { .. } compiles though. -

And you should correct your code. You declare data variable but use map in cycle. Also may be add imports? As I see you use import static java.util.Map.Entry; it's not very obvious though. -

@BalusC it gives error: incompatible types: for(Map.Entry entry : data.entrySet()) { java 1.7.0 ubuntu 11.04 -

@BalusC nope. For me it doesn't compile on mac, java 1.6.0_26. Same error. Code pastebin.com/mnQ6ZweT -

Are you sure its an error and not a "Unchecked type" warning? -

2 Respuestas

Al entrySet method signature is Set<Map.Entry<K, V>> entrySet() so you can only refer to Map.Entry if you've declared the generic types in the declaration like you did in the first example. In the second you're using raw types, so it's essentially Set<Object> entrySet() and you'd need a cast for it to work, e.g.

final Map map = new HashMap();

for(final Entry entry : (Set<Entry>)map.entrySet()) {
   // 
}

Respondido 28 ago 11, 08:08

Porque es Set<Object> entrySet() y no Set<Map.Entry<Object, Object>> entrySet()? - Mikita Belahlazau

@Nikita, that would be meaningful if a raw type was the same as the original type instantiated with unrestricted wildcards. But it can't be, because it is expected that the user of a raw type does not know about generics at all -- therefore it makes sense for its methods always to take and return raw types themselves. - hmakholm dejó a Monica

No es Set<Object>, es solo Set. - Mark Peters

Burt has the right reason and Henning expands on it in the comments. When referencing a member of a raw type, generics don't come into play en absoluto, even generics that don't rely on the type parameter.

As an example, this should compile just fine...

public class DataHolder<T> {
    public List<T> ts;
    public List<String> strings = new ArrayList<String>();
}

//...
DataHolder holder = new DataHolder();
holder.strings.add(Integer.valueOf(42));

...aunque T doesn't need to be mapped to a concrete type to know what the type of strings debiera ser.

This is true for generic member métodos as well, which is what you are running into. entrySet returns the raw type Setno, Set<Entry>, even though the type parameters would not need to be known to return a Set<Entry>. The behaviour is documented in the Especificación del lenguaje Java, sección 4.8:

El tipo de constructor (§8.8), método de instancia (§8.8, §9.4), or non-static field (§8.3) M of a raw type C that is not inherited from its superclasses or superinterfaces is the erasure of its type in the generic declaration corresponding to C. The type of a static member of a raw type C is the same as its type in the generic declaration corresponding to C.

It's a very "gotcha" rule.

Véase también

Conflictos genéricos de clase Java y genéricos de método

contestado el 23 de mayo de 17 a las 14:05

Thought your explanation was confusing and didn't believe your code example was correct (i.e. strings.add(Integer) compiles) until I tried it myself. Immediately, your explanation makes perfect sense, especially the bold and emphasis part. - Causalidad

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.