错误的论点:为什么List <List <>>与List <Object>不相等?

时间:2019-09-10 19:20:30

标签: java

下面的代码给我一个编译错误:

public static Function<int[], Stream<Tuple2<Formatter, List<Object>>>> acquisitionColors = (col) -> Seq.of(
            Tuple.tuple(Formatter.COLOR,
                    Seq.of(
                            Seq.of(col).toList(),
                            Seq.of(
                                    Seq.of("Stop", "Stoq", null, "red").toList(),
                                    Seq.of("Learning", "Learninh", null, "gray").toList(),
                                    Seq.of("Stop", "Stoq", null, "red").toList(),
                                    Seq.of("Reduce", "Reducf", null, "orange").toList(),
                                    Seq.of("Keep", "Keeq", null, "green").toList(),
                                    Seq.of("Increase", "Increasf", null, "blue").toList()
                            ).toList()
                    ).toList()
            )
    );
Wrong 2nd argument type. Found: 'java.util.List<java.util.List<? extends java.lang.Object>>', required: 'java.util.List<java.lang.Object>' 
Inspection info:  
tuple (Formatter,java.uti.List<java.lang.Object>) in Tuple cannot be applied 
to (Formatter,java.util.List<java.util.List<? extends java.lanq.Object>>)

但是,如果我用Collections.singletonList包装该列表,它将起作用:

public static Function<int[], Stream<Tuple2<Formatter, List<Object>>>> acquisitionColors = (col) -> Seq.of(
            Tuple.tuple(Formatter.COLOR,
                    Collections.singletonList(
                     ...
                    ).toList())
            )
    );

为什么会这样?

3 个答案:

答案 0 :(得分:3)

答案的两个部分: List<Object>是不变的,因此无法将类型为List<List<? extends java.lanq.Object>>的表达式分配给List<Object> Google针对Java的差异,例如: DZone article on variance in Java

public static <T> List<T> singletonList(T o)是一种通用方法。对于通用方法,应用类型推断。在您的上下文中,T应该是一个对象,并且List<List<? extends java.lanq.Object>>可以强制转换为一个对象。 参见What is type argument inference

答案 1 :(得分:1)

  

为什么不能将List<List<Object>>投射到List<Object>List<Object>也不是Object吗?

因为Java Generics are not implicitly polymorphic.List<Object>意味着它可以在给定列表中包含任何Object,甚至可以包含Map<?, ?>,但是当您将其强制转换为List<List>时,包含任何内容都不再有意义Object,并且仅限于List

  

使用Collections.singletonList()时如何工作?

仅仅是因为Collections.singletonList()返回了List<T> as per the docs,所以编译器在运行时不会抱怨它。在编译期间,请参阅Lesiak关于类型参数推断的答案。

答案 2 :(得分:-1)

您应该看一下用Java键入擦除和原始类型。

列表使用泛型,因此当您尝试创建定义原始类型的列表时,它会使用Object

List list;
// means that list holds Objects

List<String> listOfStrings;
// means that list holds Strings

对于List<List>

列表是一个interface,没有合适的强制转换形式作为Object,因为JVM在评估此语句时会注意到您正在尝试使用既不是对象也不是其子项的项目。 / p>

List<List<? extends java.lanq.Object>> // (Object or children of it)