5

为什么

List<Map<String, Object>> a, b;
a.addAll(b);

编译

List<? extends Map<String, ?>> a, b;
a.addAll(b);

才不是。

如何使后者编译?

4

6 回答 6

2

想象一下,CustomHashMap扩展HashMap,你初始化a如下:

List<CustomHashMap<String, String> list = new ArrayList<CustomHashMap<String, String>>();
List<? extends Map<String, ?>> a = list;

如果您能够将条目添加到a...

a.add(new HashMap<String, String>());

...你会遇到这种奇怪的情况

CustomHashMap<String, String> map = list.get(0); // you would expect to get CustomHashMap object but you will get a HashMap object instead

换句话说,您不知道 Map 的实际类型(当您说 ? extends Map 时),您所知道的只是它是 Map 的某个子类型,并且您不能将任意对象添加到 List,因为您需要确保添加的对象有一个超类型。但是你不能,因为地图的确切类型是未知的。

于 2013-08-30T09:28:58.793 回答
1

根据java 文档,您可以在这种情况下声明辅助方法(丑陋但有效):

static <T extends List<K>, V, K extends Map<String, V>> void addAllHelper(T from, T to) {
        from.addAll(to);
}
于 2013-08-30T09:19:21.637 回答
1

您不能将项目添加到通配符通用列表。第一个编译,因为它有一个定义的类型。

但是,您可能会找到一些适合您的目的的超类并将其用作通用参数。

更新:

另请参阅通配符(在 Oracle 文档中)

于 2013-08-30T08:39:18.647 回答
-1

下面的代码应该可以帮助您解释这一点

List<? super Number>a 称为out参数,可用于更新 List<? extends Number> b称为in参数,可用于读取

由于注释中提到的原因,下面的注释行会导致编译错误

public static void main(String[] args) {
    List<Integer> intList = new ArrayList<>();
    List<Double> doubleList = new ArrayList<>();
    List<Number> numberList = new ArrayList<>();
    addAll(numberList, intList);
    addAll(numberList, doubleList);
    addAll(intList, doubleList);//cant add double to int
    addAll(doubleList,intList);//cant add int double
    addAll(intList, numberList);//cant add number to int
}

private static<T> void addAll(List<? super T> a, List<? extends T> b) {
    a.addAll(b);
}
于 2013-08-30T09:49:53.047 回答
-1

当您使用具体的通用类型声明它时,它会编译。如果你定义一个类:

public class AClass<T extends Map<String, ?>> {

    public List<T> dostuff() {

        List<T> lista = new ArrayList<T>();
        List<T> listb = new ArrayList<T>();

        lista.addAll(listb);
        return lista;
    }
}

使用通配符无法编译。

于 2013-08-30T08:54:47.930 回答
-1

您可以使用以下方法执行此操作:

private <S extends Map<String, ?>> void method(List<S> a, List<S> b){
    a.addAll(b);
}
于 2013-08-30T09:20:04.323 回答