为我揭开通配符的神秘面纱

时间:2010-01-07 23:36:14

标签: java generics wildcard

为什么我在这段代码上出现编译时错误?

public Interface Location {
 .......
}

班级代码......

 Map<Type, List<? extends Location>> locationsTypeMap = new HashMap<Type, List<? extends Location>>();
  /**
   Code to add elements to the hashMap.
  */
  newLocation = getNewLocation()
  while(mapHasElements){
    Location.Type key = location.getType();
    List<? extends Location> valueList = (List<? extends Location>)locationsTypeMap.get(key); //1
    valueList.add(newLocation);/*Compile error*/
  }

另一方面,如果我将步骤1替换为下面的行,则可以使用

List<Location> valueList = (List<Location>)locationsTypeMap.get(key);

2 个答案:

答案 0 :(得分:11)

通配符“?extends Location”表示“我希望List<T>为某些T TLocation的子类(或{{1}本身)。“

现在,让我们把它留到一边一秒钟。你期望这个编译:

Location

?我不这么认为 - 你不能将一个简单的“对象”添加到字符串列表中。字符串列表中的任何项都必须是字符串。

回到你的第一件事。假设List<String> strings = new List<String>(); strings.add(new Object()); 返回一个对象(逻辑上 - 暂时忽略类型擦除)a locationsTypeMap.get(key) - 但假设newLocation实际上是List<ExoticLocation>的一个实例。您不应该将BoringLocation添加到BoringLocation并且编译器知道 - 所以它会阻止它发生。

来自 List<ExoticLocation>的任何内容都保证是某种List<? extends Location> ...但您无法添加任何内容。 Location反之亦然:您不能保证从super获得的任何内容都是List<? super Location>,但您可以添加Location 1}}到它。

举一个非常不同的例子:是一堆香蕉是水果的集合吗?嗯,从某种意义上说 - 你从中得到的任何东西都是的果实。但它不在另一个,因为你不能添加任何旧的水果 - 如果你试图添加一个苹果,它会脱落:)

有关详情,请参阅Angelika Langer's Java Generics FAQ

答案 1 :(得分:-1)

它是一个可以为空的类型:

http://msdn.microsoft.com/en-us/library/1t3y8s4s%28VS.80%29.aspx

编辑:鉴于上述两个答案,我一定是错的!遗憾!