为什么Java Generics的这种使用不能编译?

时间:2009-11-24 15:11:54

标签: java generics

对于我的生活,我无法理解为什么编译器不会让我做以下事情......

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);
   }
}

为什么行this.map.put(key, item)会导致编译错误?

我知道我可以更改地图声明以使用Number而不是? extends Number来使其正常工作,但在我看来,我所做的事情完全合法,我更愿意不允许地图中的Number对象。我使用的是Java 1.6.0_13。

3 个答案:

答案 0 :(得分:10)

You can't insert into collections that use wildcard types。这是因为,虽然List<Float>可以传递给接受List<? extends Number>的方法,但在其中插入Long是不安全的。在您的情况下,人们可能希望编译器更好地了解,因为集合的定义是如此可见,但事实并非如此。

答案 1 :(得分:7)

这与仿制协方差有关。

宣布时,

Map<Integer, ? extends Number> map

您无法在地图中插入任何内容,因为您无法保证? extends NumberLong

想象一下这种情况:

   Map<Integer, ? extends Number> map = new HashMap<Integer, Integer>();

   public void put(Integer key, Long item) {
      this.map.put(key, item);
   }

此处Integer != Long但两者都服从? extends Number

答案 2 :(得分:0)

将通配符提供给泛型类型有效地使其成为只读。