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

Joh*_* MD 3 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);
   }
}
Run Code Online (Sandbox Code Playgroud)

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

我知道我可以改变使用地图的声明Number而不是? extends Number让它起作用,但在我看来,我所做的是完全合法的,我宁愿不允许地图中的Number对象.我使用的是Java 1.6.0_13.

And*_*ffy 10

您无法插入使用通配符类型的集合.这是因为,虽然List<Float>可以将a传递给接受的方法List<? extends Number>,但在其中插入a是不安全的Long.在您的情况下,人们可能希望编译器更好地了解,因为集合的定义是如此可见,但事实并非如此.

  • 您可以插入使用通配符类型的collecitons.你必须正确地做到这一点.PECS规则:Producer扩展消费者超级,这意味着如果你从集合中获取,那么使用<?扩展Number>,如果要将对象放入其中,则使用<?超级数>.如果你有List <?超级数>,你可以插入一个龙.它允许您灵活地传递List <Object>或List <Number>等. (2认同)

bru*_*nde 7

这与泛型协方差有关.

当你申报时,

Map<Integer, ? extends Number> map
Run Code Online (Sandbox Code Playgroud)

你不能在地图上插入任何东西,因为你不能保证它? extends Number是一个Long,例如.

想象一下这种情况:

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

   public void put(Integer key, Long item) {
      this.map.put(key, item);
   }
Run Code Online (Sandbox Code Playgroud)

在这里,Integer != Long但都服从? extends Number.