将 a 分配List<Object>
给 aList<? super String>
工作正常。
将 a 分配List<List<Object>>
给 aList<List<? super String>>
不会编译。
代码
public class Main {
public static void main(String[] args) {
// works fine
List<Object> listOfObject = new ArrayList<>();
takeListSuperString(listOfObject);
// doesn't compile
List<List<String>> listOfListOfObject = new ArrayList<>();
takeListOfListSuperString(listOfListOfObject);
}
static void takeListSuperString(List<? super String> listSuperString) {
}
static void takeListOfListSuperString(List<List<? super String>> listOfListSuperString) {
}
}
问题
为什么不List<List<? super String>>
一样List<? super String>
?
另外,知道我可以在哪里查找这样的东西吗?
一个相关的问题是Generics hell: hamcrest matcher as a method parameter。但我觉得那里的答案没有帮助。
编辑
在我最终得到它之前,我不得不考虑JB Nizet 的答案几个小时。所以我会在这里稍微扩展一下。也许这会帮助别人。
假设将 a 分配List<List<CharSequence>>
给 aList<List<? super String>>
是可能的,以下代码将编译:
// can only contain instances of CharSequence
List<List<CharSequence>> listOfListOfCharSequences = new ArrayList<>();
List<List<? super String>> listOfListSuperString = listOfListOfCharSequences;
// add a list of objects containing an Integer
List<Object> listOfObjects = new ArrayList<>();
listOfObjects.add(123);
listOfListSuperString.add(listOfObjects);
// Ups.. exception at runtime we are getting an Integer where we expect a CharSequence
CharSequence charSequence = listOfListOfCharSequences.get(0).get(0);
因此,为了防止在运行时出现丑陋的异常,这是不允许的。
正如halex 指出的那样,这是泛型协方差,与List<String>
不可分配给相同List<Object>
。并且使用List<? extends List<? super String>>
代码实际上会编译,因为? extends String
阻止了List.add()
调用。