Why does this use of Java Generics not compile?
For the life of me I cannot understand why the compiler won't let me do the following...
import java.util.HashMap;
import java.util.Map;
public class TestMap {
private final Map<Integer, ? extends Number> map = new HashMap<Integer, Number>();
public void put(Integer 开发者_开发知识库key, Long item) {
this.map.put(key, item);
}
}
Why does line this.map.put(key, item)
cause a compile error?
I know that I can change the declaration of map to use Number
rather than ? extends Number
to make it work but it seems to me that what I am doing is perfectly legal, and I would prefer to not allow Number objects in the map. I am using Java 1.6.0_13.
You can't insert into collections that use wildcard types. This is because, while a List<Float>
can be passed to a method that accepts List<? extends Number>
, it isn't safe to insert a Long
into it. In your case, one might expect the compiler to know better as the definition of the collection is so visible, but it doesn't.
This is related to generics covariance.
When you declare,
Map<Integer, ? extends Number> map
you can't insert anything to the map because you can't guarantee that ? extends Number
is a Long
, for instance.
Imagine this situation:
Map<Integer, ? extends Number> map = new HashMap<Integer, Integer>();
public void put(Integer key, Long item) {
this.map.put(key, item);
}
Here, Integer != Long
and yet both obey ? extends Number
.
Supplying the wildcard to a generic type effectively makes it read-only.
精彩评论