开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜