2013-08-28 90 views
1

我正嘗試使用ConcurrentSkipListMap創建地圖地圖。如果我創建一個簡單的圖示例,它似乎是罰款:嘗試創建地圖地圖時出現不兼容類型錯誤

Map<Integer, Integer> mmap2 = new ConcurrentSkipListMap<Integer, Integer>(); 

有一次,我嘗試製作一張地圖,我得到一個Incompatible types錯誤:

Map<Integer, Map<Integer, Integer>> mmap = 
    new ConcurrentSkipListMap<Integer, ConcurrentSkipListMap<Integer, Integer>>(); 

如果我切換定義,包括一個ConcurrentSkipListMap,它編譯沒有問題:

Map<Integer, ConcurrentSkipListMap<Integer, Integer>> mmap = 
    new ConcurrentSkipListMap<Integer, ConcurrentSkipListMap<Integer, Integer>>(); 

爲什麼不能我定義地圖的使用Map界面的地圖嗎?

+0

這是很有意思的內部地圖參考。我本來期望能夠工作。 – Cruncher

+0

啊,是的,它是有道理的,它不應該工作。當你創建一個新的ConcurrentSkipListMap >()時,你實際上並沒有實例化第二個skiplistmap。因此,您創建的地圖不會接受不是跳過列表地圖的地圖,原始定義必須保證 – Cruncher

+0

[列表列表的子類可能重複?爲什麼不是Java的泛型隱式多態?](http://stackoverflow.com/questions/2745265/is-listdog-a-subclass-of-listanimal-why-arent-javas-generics-implicitly-p) –

回答

2

我可以回答用一個例子的問題。

Map<Integer, Map<Integer, Integer> mmap = new ConcurrentSkipListMap<Integer, ConcurrentSkipListMap<Integer, Integer>>(); 

mmap.put(5, new HashMap<Integer, Integer>()); 

在這種情況下,您是否希望放置放置線?如果它不被允許,那麼它會打破mmap的定義。如果允許的話,它會打破右手邊。

你已經產生了一行代碼,無論它是否有效,都會給你一個矛盾。因此我們不允許這樣定義mmap。

+3

請問downvoter請解釋他們的downvote? –

0

繼承不適用於泛型type parameters
您可以使用通配符如下。

Map<Integer, ? extends Map<Integer, Integer>> mmap = new ConcurrentSkipListMap<Integer, ConcurrentSkipListMap<Integer, Integer>>(); 

更多信息閱讀java subtyping

+1

也許是關於爲什麼是這樣的解釋,類似於我的評論(但有組織)是爲了。 – Cruncher

+1

你將無法添加任何東西到你的'地圖'。嘗試一下! –

0

Polymorphism的概念不像擴展到類一樣擴展到Java泛型。這就是爲什麼ConcurrentSkipListMap<Integer, ConcurrentSkipListMap<Integer, Integer>>不被視爲Map<Integer, Map<Integer, Integer>>的子類型,因此無法分配。

造成這種情況的原因泛型只提供編譯時類型安全。在運行時,通用類型由於所謂的類型擦除而未知。所以,基本上編譯正試圖阻止這種

// if this was allowed 
List<Shape> shapes = new ArrayList<Circle>(); 

// and some place else in your code 
shapes.add(new Square()); // Square now fits in a Circle list 

這將打破ArrayList通用類型,會拋出錯誤;因爲,類型是有效的,哪些不是,在運行時不知道。但是,如果你說,「嘿,這就是我想要的!Square去在Shape列表。」然後定義列表,這樣使用new ArrayList<Shape>()編譯器將符合。

所以,你只需要讓你的任務作爲

Map<Integer, Map<Integer, Integer>> mmap = 
        new ConcurrentSkipListMap<Integer, Map<Integer, Integer>>(); 

即傾向於使用接口的使兩側相一致,同時使用泛型。

編輯:(針對@ PaulBellora的downvote)

還有一個原因,爲什麼你可以指定一個Circle[]Shape[]但不ArrayList<Circle>ArrayList<Shape>。原因是,如果你的代碼試圖通過Shape[]引用將Square添加到Circle[]引用中,你將在運行時得到ArrayStoreException,因爲JVM會知道數組的實際類型。

但是,由於類型擦除相同運行時類型的安全不能擴展到集合,因此泛型類型不在同一變種。如果問題是爲什麼如果在運行時知道它的類型會消失,那麼顯然會有好處;答案應該是與Java 5之前的代碼庫很好地搭配。

+1

-1泛型不是協變的原因不是類型刪除。 –

+0

@PaulBellora,補充我的迴應作爲更新。請留下回應,說明你爲什麼認爲你是對的。 –

+0

@TheOtherDownVoter,請留意留下回復。與能夠支持他們說話的人會面很愉快。 –

-1

你可以試試這個在這裏你將有Map對象

public class GenericTest { 

    void fun(){ 
     Map<Integer, Map<Integer, Integer>> mmap = new HashMap<Integer, Map<Integer, Integer>>(); 

     Map<Integer, Integer> map = new HashMap<Integer, Integer>(); 

     mmap.put(5,map); 
    } 
} 
+0

不回答「爲什麼我不能使用Map接口定義地圖的地圖?」 –

相關問題