Generic method is not applicable for the arguments

2.9k views Asked by At

Sorry for the yet another "Java generic method is not applicable" question. I would like to know what am I missing in my understanding:

  1. List<E> is a subtype of Collection<E>
    --> meaning, List<String> is a subtype of Collection<String>

  2. Suppose A extends B, List<A> is not a subtype of List<B>
    --> but in this case, there's only one type T (or String), so I don't see how the Substitution Principle can explain my problem?

Problem Code:

private <T, K> void genericAddToMapOfLists(HashMap<K, Collection<T>> mapOfLists, 
    K key, T value) {
    if (mapOfLists.containsKey(key)) {
        mapOfLists.get(key).add(value);
    } else {
        List<T> newList = new ArrayList<T>();
        newList.add(value);
        mapOfLists.put(key, newList);
    }
}

private void parseToFruitList(HashMap<String, List<String>> fruit_colors,
        String fruitName) {
    String color = "";
    genericAddToMapOfLists(fruit_colors, fruitName, color);
}

Error:

The method genericAddToMapOfLists(HashMap<K,Collection<T>>, K, T) in the type MyGroceryStore is not applicable for the arguments (HashMap<String,List<String>>, String, String)

The code works when I change the method signature to genericAddToMapOfLists(HashMap<K,List<T>>, K, T).

2

There are 2 answers

0
rgettman On BEST ANSWER

You're right in that "List<String> is a subtype of Collection<String>". And if A extends B, List<A> is not a subtype of List<B>.

Taking that one step further, a HashMap<String, List<String>> is not a HashMap<String, Collection<String>>.

The same reasoning applies, where A is List and B is Collection. If a HashMap<String, List<String>> was a HashMap<String, Collection<String>>, then you could put a Vector<String> into a HashMap<String, List<String>> by assigning it to a HashMap<String, Collection<String>>, even though a Vector isn't a List, and so it's not allowed.

0
Sotirios Delimanolis On

This is exactly the problem you are explaining in your second point.

Suppose A extends B, List<A> is not a subtype of List<B>

In this case your method expects

HashMap<?, Collection<?>>

but you are giving it

HashMap<?, List<?>>

List extends Collection, but HashMap<?, List> is not a subtype of HashMap<?, Collection>

(I'm not using ? as a wildcard, we just don't care about it right now)