2012-04-26 63 views
1

我有一个对象定义如下:泛型通配符的正确使用

protected Map<String, ? extends List<? extends LightGeometry>> geoms=new HashMap<String,List<LightGeometry>>(); 

我尝试的对象,看起来符合通配符

ArrayList<LightGeometry> points=new ArrayList<LightGeometry>(); 
points.add((LightGeometry)new LightPoint(pt)); 
geoms.put("point", points); 

编译器插入抛出一个错误,指出:

方法put(String, capture#18-of ? extends List<? extends LightGeometry>)类型Map<String,capture#18-of ? extends List<? extends LightGeometry>>不适用于参数(String, ArrayList<LightGeometry>)

我错过了什么?

编辑:为什么我使用与泛型类型 它基本上可以归结为能够在列表(我通过服务获得)分配给该geoms对象,它是在另一个类的通配符,没有必须筛选清单才能投射。

public void onSuccess(Map<String, ArrayList<LightPolygon>> result) { 
    // TODO Auto-generated method stub 
    GWT.log("" + result.size()); 
    Log.debug("" + result.size()); 
    long startTime = System.currentTimeMillis(); 
    if (overlay != null) { 
     overlay.setData(result); 
     overlay.update(); 
     Log.debug("time to add features: " 
       + (System.currentTimeMillis() - startTime)); 
    } 
} 

如果我让geoms变量Map<String, List<LightGeometry>>然后我得到一个错误铸,说,我不能指定一个Map<String,ArrayList<LightPolygon>>到“地图>`

+0

我希望能够在不使用铸造的情况下插入值 – giscope 2012-04-26 19:32:18

回答

7

一个普通的通配符并不意味着“任何延伸List的东西“它意味着”扩展List的一些特定事物,但我不知道具体是什么。“

因此,将任何内容添加到集合是非法的,因为您不知道具体是什么!它可以是LinkedLists的一个映射,在这里你将一个ArrayList放入其中,当他们认为它是一个LinkedList时,会导致其他人得到类转换异常。

如果你想要一个包含任何类型的列表的地图,只要将它声明为一个列表地图,而不是地图?扩展List。

-

TL;博士 - 这你想要做什么,而不通配符。通配符通常用于指定方法签名,如果您知道类型是什么,则无关紧要。如果你只是想要一个包含子类的集合,你只需指定超类型。

例如:

Map<String, List<Number>> map = new HashMap<String,List<Number>>(); 

List<Number> integers =new ArrayList<Number>(); 
integers.add(Integer.valueOf(1)); 
map.put("integers", integers); 

List<Number> floats = new LinkedList<Number>(); 
floats.add(Float.valueOf(5.2f)); 
map.put("floats", floats); 

没有铸造!

+1

Java泛型不是协变的,它本质上是非类型安全的。编译器迫使你进行强制转换,让你说“我知道这个集合不再能保证编译器的类型安全。”如果您不想进行演员表演,您必须将您的列表声明为分母列表。 – Affe 2012-04-26 22:11:01

+0

真棒男人..谢谢一堆! – giscope 2012-04-26 22:23:15