1

This following code gives me a compilation error:

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>>)

However, if I wrap that list with a Collections.singletonList, it works:

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

Why does that happen?

ftkg
  • 1,652
  • 4
  • 21
  • 33

3 Answers3

3

Two parts of an answer: List<Object> is invariant, thus expression typed as List<List<? extends java.lanq.Object>> cannot be assigned to List<Object> Google for variance in Java, for example: DZone article on variance in Java

public static <T> List<T> singletonList(T o) is a generic method. For generic methods type inference is applied. In your context, T is expected to be an Object, and List<List<? extends java.lanq.Object>> can be cast to an Object. See What is type argument inference

Lesiak
  • 22,088
  • 2
  • 41
  • 65
1

Why can't I cast a List<List<Object>> to List<Object>? isn't List<Object> an Object too?

Because Java Generics are not implicitly polymorphic.. List<Object> means it can have any Object in the given list, even a Map<?, ?>, but when you cast it to a List<List>, It no longer makes sense to be containing any Object and is limited to only List

How does it work when use Collections.singletonList() ?

Simply because Collections.singletonList() is returning a List<T> as per the docs so the compiler won't be complaining about it during runtime. See Lesiak's answer about Type Argument Inference during compile time.

Irshad P I
  • 2,394
  • 2
  • 14
  • 23
  • 1
    `Collections.singletonList() is infact returning a List as per the docs.` I believe you are misinterpreting the docs. – Lesiak Sep 10 '19 at 20:08
-1

You should take a look to type erasure and raw type in Java.

Lists use generics so when your try to create a list with defining raw type it uses Object

List list;
// means that list holds Objects

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

Now for the case of List<List>

List is an interface which has no suitable casting as an Object there for when evaluating this statement the JVM notice that you are try to use items that are neither Objects or 'children of it'

List<List<? extends java.lanq.Object>> // (Object or children of it)
Hassam Abdelillah
  • 2,246
  • 3
  • 16
  • 37