2012-07-23 67 views
2
通用功能

我試圖寫一個通用的函數將接受以下兩個數據類型對地圖的地圖在Java中

Map <Integer, Map<Integer, Long>> 
Map <Integer, Map<Integer, Double>> 

我的功能看起來是這樣的,

function(Map<Integer, Map<Integer, ? extends Number>> arg) {} 

但我我得到一個不兼容的類型錯誤。它適用於地圖,但不適用於地圖地圖。我無法理解爲什麼?有沒有辦法做到這一點?

回答

2

首先讓我們通過使用Set!而非減少的問題:

Set<Set<Long>> longSetSet = null; 
Set<Set<Double>> doubleSetSet = null; 

Set<Set<? extends Number>> someNumberSetSet; 

// try assigning them 
someNumberSetSet = longSetSet; // 
someNumberSetSet = doubleSetSet; // compiler errors - incompatible types 

乍一看,你可能會奇怪,爲什麼這個任務是非法的,因爲畢竟你可以指定一個Set<Long>Set<? extends Number>的原因是generics are not covariant。編譯器會阻止您將Set<Set<Long>>指定爲Set<Set<? extends Number>>,原因與它不允許將Set<Long>指定爲Set<Number>的原因相同。有關更多詳細信息,請參閱關聯答案

作爲解決方法,您可以在方法簽名中使用類型參數作爲其他答案的建議。您還可以使用通配符另一個使分配的法律:

Set<? extends Set<? extends Number>> someNumberSetSet; 

someNumberSetSet = longSetSet; // 
someNumberSetSet = doubleSetSet; // legal now 

或者在你的榜樣:

function(Map<Integer, ? extends Map<Integer, ? extends Number>> arg) { } 
3

你可以嘗試像

static <T extends Number> void function(Map<Integer, Map<Integer, T>> map) {} 

public static void main(String[] args) { 
    Map<Integer, Map<Integer, Long>> map1 = new HashMap<Integer, Map<Integer, Long>>(); 
    Map<Integer, Map<Integer, Double>> map2 = new HashMap<Integer, Map<Integer, Double>>(); 
    Map<Integer, Map<Integer, String>> map3 = new HashMap<Integer, Map<Integer, String>>(); 
    function(map1); 
    function(map2); 
    function(map3);// <-- compilation error here, String is not Number 
} 
+0

甜。有用。有什麼地方可以閱讀爲什麼我的功能不起作用嗎? :) – Blacklabel 2012-07-23 00:14:38

2

爲什麼不只是參數的方法?

public <T extends Number> void function(Map<Integer, Map<Integer, T>>) { ... } 

我發現通配符捕獲容易讓人們誤解它的真實含義。

Map<Integer, ? extends Number>確實是指任何Map,其關鍵是Integer,其值是從Number派生的類型。這意味着Map<Integer, Integer>,Map<Integer,Long>

因爲這個原因,你永遠不可能真的添加到這些集合中,因爲通配符編譯器不能告訴真實類型是爲了添加。

0
static void test(Map<Integer, Map<Integer, ? extends Number>> a) { } 

這實際上對我來說工作得很好(JavaSE-1.6)。