Multimaps中的Java Generics擦除

时间:2013-04-16 16:12:40

标签: java generics guava

我有两个由{i} Multimap和(ii)String索引的IntegerDouble以及一个输出{{{ 1}}秒。

String

我想将public static void outputInteger(Multimap<Integer, String> map) { for (Integer key : map.keySet()) { Collection<String> strings = map.get(key); output(strings); } } public static void outputDouble(Multimap<Double, String> map) { for (Double key : map.keySet()) { Collection<String> strings = map.get(key); output(strings); } } 作为NumberInteger

的超类,将这些组合成一个例行程序
Double

但带星号的行无法编译

public static void outputNumber(Multimap<? extends Number, String> map) {
    for (Number key : map.keySet()) {
        Collection<String> ids = map.get(key); //** 
    }
}

我该如何解决这个问题?

4 个答案:

答案 0 :(得分:9)

声明

Multimap<? extends Number, String> map;

表示地图的密钥类型是未知但具有数字的特定子类型(包括)。换句话说,编译器认为它可能是Multimap<Integer, String>Multimap<Short, String>Multimap<Number, String>等。因此,您无法调用map.get(Number),因为到目前为止正如编译器所知,它可能是Multimap<Double, String>

使用put更明显无法做到这一点。你应该put(Number, String) map吗?不,因为如果它恰好是Multimap<Integer, String>,那么您可以添加一个Double密钥,这将违反地图的完整性。

使用正常的Map<K, V>界面,这不是问题,因为get定义为get(Object),而不是get(K)

保罗的回答对这种情况有很好的解决方法。本质上,他使用中间泛型方法为未知类型(在本例中由capture#5-of ? extends Number表示)提供名称(类型参数T)。这允许您关联在两个不同上下文中发生的捕获,以便您可以跨这些上下文执行某些操作。

答案 1 :(得分:7)

您应该可以使用generic method来实现您的目标:

public static <T extends Number> void outputNumber(Multimap<T, String> map) {
    for (T key : map.keySet()) {
        Collection<String> strings = map.get(key);
        output(strings);
    }
}

它不适用于通配符的原因是因为? extends Number表示某些未知类型Number。同时,Number key可以引用其他一些不兼容的类型(对于所有编译器都知道)。

答案 2 :(得分:7)

public static void output(Multimap<? extends Number, String> map) {
    for (Collection<String> strings : map.asMap().values()) {
        output(strings);
    }
}

答案 3 :(得分:0)

问题是你没有传递泛型参数但声明它。

如果您有这种类型的实现,则不会发生错误

public static <T extends Number> void outputNumber(Multimap<T, String> map) {

        for (T key : map.keySet()) {
            map.get(key);
        }
    }