名单<名单<?超级字符串>无法按预期工作

Are*_*rff 1 java generics

分配List<Object>List<? super String>工作正常.

分配List<List<Object>>给a List<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) {

    }
}
Run Code Online (Sandbox Code Playgroud)

为什么不List<List<? super String>>一样List<? super String>

另外,任何想法,我可以在哪里查找这样的东西?

一个相关的问题是Generics hell:hamcrest matcher作为方法参数.但我没有找到有帮助的答案.

编辑

在我终于得到它之前,我必须通过JB Nizet的答案思考几个小时.所以我会在这里稍微扩展一下.也许这会帮助别人.

假设分配List<List<CharSequence>>List<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);
Run Code Online (Sandbox Code Playgroud)

因此,为了防止运行时出现丑陋的异常,不允许这样做.

正如halex所指出的那样,这是泛型协方差,与List<String>不可分配的相同List<Object>.并且使用List<? extends List<? super String>>代码实际上会编译,因为? extends String阻止了List.add()调用.

JB *_*zet 7

因为a List<Object>与a 不是一回事List<? super String>.A List<? super String>保存一个您不知道的特定类型的对象,但它是String或String的超类或超级接口.而a List<Object>是一个可以容纳任何类型对象的List.

假设? super StringCharSequence.你会发现以下编译是正常的吗?

List<List<Object>> listOfListOfObjects = new ArrayList<List<Object>>();
List<Object> listOfObjects = new ArrayList<Object>(); 
listOfObjects.add(new Integer());
listOfListOfObjects.add(listOfObjects);
List<List<CharSequence>> listOfListOfCharSequences = listOfListOfObjects; // WTF?
Run Code Online (Sandbox Code Playgroud)