Java type inference doesn't work as I expect

I have this method (this is a simplification of my original problem):

public List<AbstractMap.SimpleEntry<String, List<?>>> method(List<?> list) {
    return Collections.singletonList(new AbstractMap.SimpleEntry<>("", list));
}

However, this leads to a compilation error:

Console.java:40: error: incompatible types
        return Collections.singletonList(new AbstractMap.SimpleEntry<>("", list));
                                        ^
  required: List<SimpleEntry<String,List<?>>>
  found:    List<SimpleEntry<String,List<CAP#1>>>
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Object from capture of ?
10 errors

If I try to specify a type instance for a top-level method:

return Collections.<AbstractMap.SimpleEntry<String, List<?>>>singletonList(new AbstractMap.SimpleEntry<>("", list));

I get another error:

Console.java:40: error: method singletonList in class Collections cannot be applied to given types;
return Collections.<AbstractMap.SimpleEntry<String, List<?>>>singletonList(new AbstractMap.SimpleEntry<>("", list));
                  ^
  required: T
  found: SimpleEntry<String,List<CAP#1>>
  reason: actual argument SimpleEntry<String,List<CAP#1>> cannot be converted to SimpleEntry<String,List<?>> by method invocation conversion
  where T is a type-variable:
    T extends Object declared in method <T>singletonList(T)
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Object from capture of ?
10 errors

Only when I specify the type parameters in the internal method does all this work:

return Collections.singletonList(new AbstractMap.SimpleEntry<String, List<?>>("", list));

I don’t even pretend to understand what is happening here. I suspect this is due to capture conversion (related question here ), but I have no idea why specifying generics on an external method does not work, but on an internal method. Does java use a return type to output type arguments for nested calls like this? What's going on here?

+4
1

, - (, new ArrayList<?>(); ). , CAP # 1, , , .

, . , .

public <T> List<AbstractMap.SimpleEntry<String, List<T>>> method(List<T> list) {
    return Collections.singletonList(new AbstractMap.SimpleEntry<>("", list));
}

​​ , .

0

All Articles