原始列表转换为List<?>正常.为什么原始列表列表不能转换为列表List<?>?
{ // works
List raw = null;
List<?> wild = raw;
}
{ // Type mismatch: cannot convert from List<List> to List<List<?>>
List<List> raw = null;
List<List<?>> wild = raw;
}
Run Code Online (Sandbox Code Playgroud)
背景故事(缓解xy问题):
我正在使用的API返回List<JAXBElement>.我碰巧知道它总是如此List<JAXBElement<String>>.我计划循环并构建自己的List<String>,但我在写时试图修复(但不是抑制)原始类型编译器警告List<JAXBElement> raw = api();.
我试过了:
List<JAXBElement<?>> raw = api();
List<JAXBElement<?>> raw = (List<JAXBElement<?>>) api();
Run Code Online (Sandbox Code Playgroud)
但这些给出了类型不匹配错误.
有趣的是,这没有任何警告或错误:
for (JAXBElement<?> e : api()) {
// ...
}
Run Code Online (Sandbox Code Playgroud) 问题的关键是,为什么这会导致编译时错误?
List<Collection> raws = new ArrayList<Collection>();
List<Collection<?>> c = raws; // error
Run Code Online (Sandbox Code Playgroud)
我理解为什么泛型一般不协变.如果我们能够分配List<Integer>到List<Number>,我们会暴露自己ClassCastExceptions异常:
List<Integer> ints = new ArrayList<Integer>();
List<Number> nums = ints; // compile-time error
nums.add(Double.valueOf(1.2));
Integer i = ints.get(0); // ClassCastException
Run Code Online (Sandbox Code Playgroud)
我们在第2行得到一个编译时错误,以避免我们从第4行的运行时错误.这是有道理的.
List<C> 至 List<C<?>>但是这个怎么样:
List<Collection> rawLists = new ArrayList<Collection>();
List<Collection<?>> wildLists = rawLists; // compile-time error
// scenario 1: add to raw and get from wild
rawLists.add(new ArrayList<Integer>());
Collection<?> c1 = wildLists.get(0);
Object o1 = c1.iterator().next();
// scenario 2: add to wild …Run Code Online (Sandbox Code Playgroud)