为什么这种方法与通配符有效?

时间:2013-11-22 11:22:52

标签: java generics wildcard bounded-wildcard

我遇到了这个问题:

我们获得了一个地图界面:

interface MyMap<K,V>{
  public void put (K key, V value);
  public V get (K key);
  public boolean containsKey (K key);
}

我们希望实现一个方法addToMyMap,其签名是(我们需要填写缺失的部分(点):

void addToMyMap(MYMap<....> m, List<....> keys, .... newValue)

该方法将扫描键列表,如果地图中不存在每个键,它将添加newValue作为值。

作为答案给出的实现如下:

 public static <K,V> void addToMyMap (MyMap <? super K, ? super V> m, List<? extends K> keys, V newValue) 
 {
   for (K key: keys)
   {
      if (!m.containsKey(key))
      {
         m.put(key,newValue);
      }
   } 
}

我不完全确定为什么这个实现是正确的。如果containsKey方法获得K的子类,它如何工作?是不是在Apple中搜索List<Fruit>?你怎么会迭代那个名单?

同样适用于put方法:如何迭代具有多种不同类型的地图?

这可能与地图的实施有关。

所以也许真正的问题是,包含许多超类型K和V的地图如何知道迭代Ks。

调用此方法的示例如下:

MyMap <Number, Number> m = new MyMapImpl<Number,Number>();
m.put(new Integer (1) , new Float(7.2));
m.put (new Float(3.1), new Double(9.99));

List<Integer> lst = new List<Integer>();
lst.add(1); lst.add(2); lst.add(3);
Float f = new Float (55.5);
Util.addToMyMap (m,lst,f);

这个映射如何保存float和整数查找一个float类型的键(在put和containsKey中)?

我很感激一些解释。

1 个答案:

答案 0 :(得分:4)

这称为The Get and Put Principle:当您只从结构中获取值时使用extends通配符,当您只将值放入结构时使用super通配符,并且<当你得到并放置时,不要使用通配符。

  

这个映射如何保存浮点数和整数查找键   float类型(在put和containsKey中)?

古怪的短语? super K表示目标Map可能包含{{1>}的超类型的任何类型的元素。这称为下限有界通配符,它​​将未知类型限制为特定类型或该类型的超类型。

例如,KList<Integer>更具限制性,因为前者仅匹配Integer类型的列表,而后者匹配任何类型的列表{@ 1}}的超类型。


对于您的上下文List<? super Integer>,其类型为Integer,它是MyMap <Number, Number> mNumber的超类型。因此,它可以包含IntegerFloat类型的元素。甚至Integer也是如此。因为它们都是Float的子类型。超类型实例始终可以引用子类型。

请查看:

  1. Lower Bounded Wildcards
  2. Guidelines for Wildcard Use