Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Inferring a generic type from a generic type in Java (compile time error)

I have a static function with the following signature for a generic type T

public static<T> List<T> sortMap(Map<T, Comparable> map)

which should return a list of map keys with some property.

Now I want to pass a generic HashMap of type S

Map<S,Double> map

in calling the static function within a generic class, which has the map as a member variable.

I have listed a minimal code example below.

However, I get an error message (S and T are both T's but in different scopes of my code, i.e. T#1 = T, T#2= S):

  required: Map<T#1,Comparable>
  found: Map<T#2,Double>
  reason: cannot infer type-variable(s) T#1
  (argument mismatch; Map<T#2,Double> cannot be converted to Map<T#1,Comparable>)

How can resolve this issue? I am surprised that Java does not allow inferring a generic type from a generic type. What structure in Java can one use to work with that kind of more abstract code reasoning?

Code:

public class ExampleClass<T> {
    Map<T, Double> map;
    public ExampleClass () {
        this.map = new HashMap();
    }
    //the following line produces the mentioned error
    List<T> sortedMapKeys = UtilityMethods.sortMap(map);
}

public class UtilityMethods {
     public static<T> List<T> sortMap(Map<T, Comparable> map) {
        // sort the map in some way and return the list
     }
}
like image 487
madison54 Avatar asked Jun 19 '15 08:06

madison54


1 Answers

It's not the problem with the T and S, but with the Comparable and Double.

The reason for the error is that a Map<T, Double> is not a Map<T, Comparable>.

You'll have to widen a bit the scope of the second type-parameter. Something like:

public static <T, S extends Comparable<S>> List<T> function(Map<T, S> map) {
    //implementation
}

Then, you'll be able to invoke the method with:

Map<S, Double> map = new HashMap<S, Double>();
function(map);
like image 168
Konstantin Yovkov Avatar answered Oct 04 '22 20:10

Konstantin Yovkov