Java中地图Map的通用函数

时间:2012-07-23 00:02:09

标签: java generics

我正在尝试编写一个接受以下两种数据类型的通用函数

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

我的功能看起来像这样,

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

但是我收到了一个不兼容的类型错误。它适用于地图,但不适用于地图地图。我无法理解为什么?有没有办法做到这一点?

4 个答案:

答案 0 :(得分: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
}

答案 1 :(得分: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>

出于这个原因,你永远不能真正添加​​到这些集合,因为通配符编译器无法分辨真正的类型是为了添加。

答案 2 :(得分: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 :(得分:0)

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

这实际上对我来说很合适(JavaSE-1.6)。