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
//
}
Any clues?
entrySet() method in Java is used to create a set out of the same elements contained in the map. It basically returns a set view of the map or we can create a new set and store the map elements into them.
Entry interface enables you to work with a map entry. The entrySet( ) method declared by the Map interface returns a Set containing the map entries. Each of these set elements is a Map. Entry object.
Map doesn't allow duplicate keys, but it allows duplicate values. HashMap and LinkedHashMap allows null keys and null values but TreeMap doesn't allow any null key or value. Map can't be traversed so you need to convert it into Set using keySet() or entrySet() method.
The 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()) {
//
}
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 at all, 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));
...even though T
doesn't need to be mapped to a concrete type to know what the type of strings
should be.
This is true for generic member methods as well, which is what you are running into. entrySet
returns the raw type Set
, not Set<Entry>
, even though the type parameters would not need to be known to return a Set<Entry>
. The behaviour is documented in the Java Language Specification, section 4.8:
The type of a constructor (§8.8), instance method (§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.
Java Class Generics and Method Generics conflicts
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With