Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot convert generic to expanded nested type

Tags:

java

generics

Recently I was refactoring a generic method when I got into generic casting issues I cannot explain. Finally I realized I could do without the T type altogether (just inline it myself), but I'm still curious as to why the convert fail. I created this minimal example to illustrate the issue.

Can someone explain me why the convert fails and the workaround works?

public <K, T extends List<K>> void castLists(List<T> list, K kForBinging) {
    Map<Integer, List<T>> map = mapSizeToList(list);
    // Type mismatch: cannot convert from Map<Integer,List<T>> to Map<Integer,List<List<K>>>
    // Map<Integer, List<List<K>>> expandedMap = map;

    // Added after accepting answer, legal assignment:
    Map<Integer, ? extends List<? extends List<K>>> expandedMap = map;

    // Originally proposed 'work around'
    Map<Integer, ?> lessSpecific = map;
    @SuppressWarnings("unchecked")
    Map<Integer, List<List<K>>> canCast = (Map<Integer, List<List<K>>>)lessSpecific;
    // ...
}

public <A> Map<Integer, List<A>> mapSizeToList(List<A> list) {
    Map<Integer, List<A>> map = Maps.newHashMap();
    // ...
    return map;
}
like image 845
Stim Avatar asked Dec 20 '12 09:12

Stim


1 Answers

I believe you need Covariance with generics before you can do such things. This doesnt seem to be supported by Java.

i.e in Java, if T is a subtype of List<K>, it does NOT imply that List<T> is a subtype of List<List<K>> or that Map<Integer,List<T>> is a subtype of Map<Integer, List<List<K>>>. This is why the assignment errors out.

Covariance would allow you to do this because with it, if template parameters have a subclass-superclass relationship, the defined classes will also have the exact same relationship. This would make this assignment possible. Scala (among other (functional programming?) languages) supports covariance and its complement contravariance.

like image 75
Karthik T Avatar answered Oct 29 '22 12:10

Karthik T