2012-01-08 13 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