4

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.

Community
  • 1
  • 1
Mike
  • 20,010
  • 25
  • 97
  • 140
  • I dont know if I am right or not, but it seems like java compiler is not able resolve or convert the collection type being used as the key to Map collection defined in the problem. I am saying this because when I modify the function signature as `public static void processMap(Map extends Object, List> map)`, it works fine. Seems like there is a great difference between `` and ` extends Object>` when used in such declarations. Its multi-level wildcards concept. – qwerty Jun 01 '16 at 12:29

3 Answers3

1

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.

Tamas Rev
  • 7,008
  • 5
  • 32
  • 49
  • I think the reason _why_ this works has something to do with [wildcard capture](https://docs.oracle.com/javase/tutorial/java/generics/capture.html). – Tamas Rev Jun 01 '16 at 10:52
  • Just posted the same ... only difference: there is no need to put the `extends Object` there. Any T that you ever will be using will be extending Object without you telling the compiler ;-) – GhostCat Jun 01 '16 at 10:53
  • Yeah. Using `` is okay now. the `extends` is good for stuff like `` – Tamas Rev Jun 01 '16 at 10:55
1

Half an answer: the following code does compile for me.

Missing: a good explanation for why a named T works; but an unnamed ? does not.

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

public void f() {
    Map<String, List<String>> map = new HashMap<>();
    processMap(map);
    Map<String, List<Object>> map2 = new HashMap<>();
    processMap(map2);
}
GhostCat
  • 137,827
  • 25
  • 176
  • 248
0
Map<String, List<? extends Object>> map = new HashMap<>();

make the above change in f() method and it work. Java compiler check the type of variable so both should be same, i may wrong.

ankush yadav
  • 422
  • 3
  • 13