Mykhaylo Adamovych Mykhaylo Adamovych - 6 months ago 11
Java Question

Generic wildcard bounderies in complex types

I don't understand generic wildcard bounderies ussage.

Could you please explain why

processList
works pretty well while
processMap
fails with compilation error in the following example? How should I change signature of
processMap
to make it work with both
Map<String, List<String>>
and
Map<String, List<Object>>


public void processList(List<? extends Object> list) {
}

public void processMap(Map<String, List<? extends Object>> map) {
}

public void f() {
List<String> list = new ArrayList<>();
Map<String, List<String>> map = new HashMap<>();

processList(list); // OK
processMap(map); // ERROR
}





While moving generic type definition from method argument type to method paramether made the trick

public void processMap(Map<String, List<? extends Object>> map)
public <T extends Object> void processMap(Map<String, List<T>> map)


I would now like to know difference between the two. Moved to another thread.

Answer

You can make it work if you eliminate the wildcard. I.e. you create a generic function with a named type: <T extends Object>

public <T extends Object> void processMap(Map<String, List<T>> map) {
}

public void processList(List<? extends Object> list) {
}

public void f() {
    List<String> list = new ArrayList<>();
    Map<String, List<String>> map = new HashMap<>();

    processList(list); // OK
    processMap(map); // OK now
    processMap(new HashMap<String, List<Integer>>()); // this is OK too
}

Unfortunately, I can't explain why the function with the wildcard doesn't work.