java泛型和addAll方法

时间:2010-04-23 19:59:45

标签: java generics collections

Java集合中addAll(..)方法的正确参数类型是什么?如果我做这样的事情:

List<? extends Map<String, Object[]>> currentList = new ArrayList<Map<String, Object[]>>();
Collection<HashMap<String, Object[]>> addAll = new ArrayList<HashMap<String, Object[]>>();
// add some hashmaps to the list..
currentList.addAll(addAll); 

我知道我需要初始化这两个变量。但是,我得到了一个编译错误(来自eclipse):

Multiple markers at this line
    - The method addAll(Collection<? extends capture#1-of ? extends Map<String,Object[]>>) in the type List<capture#1-of ? extends Map<String,Object[]>> is not applicable for the arguments (List<capture#2-of ? extends 
     Map<String,Object[]>>)
    - The method addAll(Collection<? extends capture#1-of ? extends Map<String,Object[]>>) in the type List<capture#1-of ? extends Map<String,Object[]>> is not applicable for the arguments 
     (Collection<HashMap<String,Object[]>>)
我做错了什么?

5 个答案:

答案 0 :(得分:8)

extends替换为super

addAll()本身会收到? extends T个参数,当T? extends Map<K, V>时,该参数无效。随着变化,它将变得有效? extends ? super Map<K, V>

但更好的方法是删除? extends(或? super)。在这种特殊情况下,它是多余的。只需使用List<Map<String, Object[]>>即可。 addAll()将有效地采用? extends Map<String, Object[]>>

答案 1 :(得分:7)

您只能将T的实例插入List<T>

类型List<? extends Map<X,Y>>代表未知类型T的列表extends Map<X,Y>。例如,它可以代表List<LinkedHashMap<X,Y>>。显然,您可能不会在这样的列表中插入普通的HashMap<X,Y>

你可能想要:

List<Map<String, Object[]>> currentList;

或者如果你想要变得非常灵活,你可以这样做:

List<? super Map<String, Object[]>> currentList;

这会让你做一些疯狂的事情:

currentList = new ArrayList<Map<? super String, ? extends Object[]>>();

您可能还希望阅读Angelika Langer的Generics常见问题解答,尤其是the section about wildcards

答案 2 :(得分:6)

请记住:

对于<? extends ...>,你不能把东西(除了null)放进去

对于<? super ...>,你不能从中得到东西(除了对象)

答案 3 :(得分:1)

您无法在此类列表上调用任何具有通用属性的方法。基本上,? extends Foo所说的是“扩展Foo”的东西,但你不知道那是什么。返回该类型时,您可以说返回的值为Foo或某个子类型。但是对于任何给定的值,你不能匹配? extends Foo generic。

简而言之:您需要更改currentList声明将其转换为List不带泛型)并发出警告或(如果你知道你在做什么的话就压制它。

答案 4 :(得分:0)

你的问题基本归结为:

public static <T extends Collection<?>> void foo(T t) {
T x = null;
x.addAll(t);
}

这将失败,基本上与您描述的错误相同。尝试沿着这些方向修改它。

public static <T extends Collection<Y>, Y> void foo(T t) {
T x = null;
x.addAll(t);
}

或者,在上面的示例中,您可以更改

List<? extends Map<String, Object[]>> currentList;

List<Map<String, Object[]>> currentList;

如果你尝试开始传递未指定的类型,泛型会很快变得毛茸茸。