Java 为我揭开通配符的神秘面纱
为什么在这段代码上会出现编译时错误Java 为我揭开通配符的神秘面纱,java,generics,wildcard,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. */ newLocat
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*/
}
Map通配符“?扩展位置”意味着“对于某些T
来说,我希望它是List
,其中T
是Location
的子类(或者是Location
本身)。”
现在,让我们暂时把它放在一边。您是否希望编译以下内容:
List<String> strings = new List<String>();
strings.add(new Object());
List strings=newlist();
添加(新对象());
??我不这么认为——你不能在字符串列表中添加一个简单的“对象”。字符串列表中的任何项都必须是字符串
回到你的第一件事。假设locationsTypeMap.get(key)
返回一个对象,该对象(逻辑上-暂时忽略类型擦除)是列表
,但假设newLocation实际上是BoringLocation的一个实例
。您不应该将BoringLocation
添加到列表中,编译器知道这一点,因此它阻止了这种情况的发生
从列表中获得的任何内容都是可为空的类型,如下所示:
编辑:鉴于以上两个答案,我一定错了!对不起 语言错误,与可空性无关。在C#中,这将是完全不正确的语法。我认为,在发布和编辑之后,我第一次在多语言论坛上发布了“对不起,新堆栈溢出”。因此,成员们早些时候为我澄清了这个确切的情况。虽然您已经接受了答案,但您可能仍然想检查一下:编译器应该警告您强制转换不安全,(List)将编译为(List),如果列表是列表,则不会引发类强制转换异常,如果插入对象,则可能会导致代码的其他部分出现类强制转换异常
List<String> strings = new List<String>();
strings.add(new Object());