2012-01-08 14 views
4

我有一个类FourByFourBoard,它扩展了GameBoard。我定义了以下字段:带泛型的Java集合给我提供了不适用的参数错误

private Map<Integer,List<Key<? extends GameBoard>>> mGameTypeToKeysMap = new Hashtable<Integer,List<Key<? extends GameBoard>>>(); 

private List<Key<FourByFourBoard>> mFourByFourBoardKeys = new ArrayList<Key<FourByFourBoard>>(); 

在我的构造函数中,我尝试拨打:

mGameTypeToKeysMap.put(Game.FOUR_BY_FOUR, mFourByFourBoardKeys); 

但我得到这个:

在类型的方法put(Integer, List<Key<? extends GameBoard>>) Map<Integer,List<Key<? extends GameBoard>>>不适用于 参数(int, List<Key<FourByFourBoard>>)

我可以使用一种不同的方法来做我想做的事情,但在盯着代码一会儿之后,我无法弄清楚为什么这种方式不起作用。

编辑

比我想的这个问题可能比较简单:

如果我尝试:

Key<GameBoard> a = mFourByFourBoardKeys.get(0); 

我得到:

类型不匹配:不能转换Key<FourByFourBoard>Key<GameBoard>

即使:

GameBoard someBoard = new FourByFourBoard(); 

是合法的。所以这仍然是一个泛型问题,但集合部分并不重要。而我的头还在旋转一点。

+0

Key是Objectify的一个类,如果有帮助的话。 http://objectify-appengine.googlecode.com/svn/trunk/javadoc/com/googlecode/objectify/Key.html – 2012-01-08 23:29:20

回答

3

一个List<A extends B>List<B>是不一样的,因为在第一列表中,您只能添加A情况下,和第二,你可以同时添加AB实例。

这是所有在Java generics tutorial非常清楚说明的那样,第4页(第泛型和子类型)

编辑

一个小例子示出这一点,并更紧密地匹配代码中的位

更具体上
Map<Integer, List<List<? extends Number>>> a = new Hashtable<Integer,List<List<? extends Number>>>(); 
List<List<Double>> b = new ArrayList<List<Double>>(); 
a.put(0, b);//won't compile 
List<List<? extends Number>> c = new ArrayList<List<? extends Number>>(); 
a.put(1, c);//works perfectly 

这个不编译的原因解释为我链接到的PDF,并引用相关部分

让我们来测试我们对泛型的理解。以下代码段合法吗?

List<String> ls = new ArrayList<String>(); //1 
List<Object> lo = ls; //2 

1号线肯定是合法的。问题的更复杂的部分是第2行。这个归结为 的问题:是一个字符串列表的对象列表。大多数人的直觉是回答: “当然!”。 好了,看看接下来的几行:

lo.add(new Object()); // 3 
String s = ls.get(0); // 4: attempts to assign an Object to a String 

我建议要经过整个PDF,并看看该文件的(其他)的例子。

+0

我可以这样做:private Map > a = new Hashtable >(); private List b = new ArrayList (); a.put(0,b); - 问题似乎是通用在密钥中。 – 2012-01-08 23:14:05

+0

@BenFlynn我编辑了我的答案 – Robin 2012-01-08 23:37:47

+0

感谢您更详细地解释和引用相关信息。 – 2012-01-09 00:11:37

1

问题是通用类型必须与完全匹配。试试这个:

private List<Key<? extends GameBoard>> mFourByFourBoardKeys = new ArrayList<Key<? extends GameBoard>>(); 

,您仍然可以添加FourByFourBoard实例名单确定,但地图现在将接受列表。

注:我测试了这个使用标准的JDK类有类似的模式,所以任何人都可以复制粘贴此代码自己:

Map<Integer, List<Comparable<? extends Number>>> map = new HashMap<Integer, List<Comparable<? extends Number>>>(); 
List<Comparable<? extends Number>> list = new ArrayList<Comparable<? extends Number>>(); 
list.add(new Long(0)); 
map.put(new Integer(1), list); 
1

?手段“一些明确的类型,我不知道”; ? extends Foo意思是'我不知道的某种确定类型,但是它延伸了Foo'。

FourByFourBoard是延伸GameBoard一个明确的类型,但是编译器不知道它是相同这样明确的类型与mGameTypeToKeysMap的定义中所提及的一个。

为了说明这一点,我认为这将被允许写:

mGameTypeToKeysMap = new Hashtable<Integer,List<Key<EightByEightBoard>>>(); 

此时你试图put将是非常错误的。

+0

谢谢,这很有帮助! – 2012-01-09 00:12:45