Search code examples
javagenerics

List class wrapped by Map class does not support generic types in Java?


Class definition

public interface ITest {
    Long foo();
}

public class Test implements ITest{

    @Override
    public Long foo() {
        return 0L;
    }
}

Methods

public Map<Long, List<? extends ITest>> moo() {
    List<Test> a = List.of(new Test());
    Map<Long, List<? extends ITest>> b = Map.of(1L, a);
    return b;
}

public Map<Long, List<? extends ITest>> koo() {
    List<Test> a = List.of(new Test());
    Map<Long, List<Test>> b = Map.of(1L, a);
    return b;
}

public List<? extends ITest> too() {
    List<Test> a = List.of(new Test());
    return a;
}

I get an error only at the koo() function. Why does this not work? Does the List class that is wrapped by the Map class not support generics?

Below is the error I get.

Incompatible types. Found: 'java.util.Map<java.lang.Long,java.util.List<Test>>', required: 'java.util.Map<java.lang.Long,java.util.List<? extends ITest>>'

I think it should work properly, but it didn't.


Solution

  • Your too method compiles because a List<Test> is a subtype of the declared return type of the method, List<? extends ITest>. Your explicit ? extends in the return type makes List<Test> a subtype.

    Your koo method does not compile because even though List<Test> is a subtype of List<? extends ITest>, a Map<Long, List<Test>> is not a subtype of Map<Long, List<? extends ITest>>. Nesting that generics relationship in another generic type is not allowed, because you're using invariant generics.

    If you removed ? extends from the return type of too, then that method wouldn't compile because List<Test> is not a subtype of List<ITest>.

    Like what is needed for too, add ? extends to the return type for koo to get this to compile. The type Map<Long, List<Test>> is a subtype of Map<Long, ? extends List<? extends ITest>> because of this added ? extends.

    //               vvvvvvvvv
    public Map<Long, ? extends List<? extends ITest>> koo() {