7

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
     }
}
madison54
  • 743
  • 2
  • 8
  • 19

1 Answers1

9

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);
Community
  • 1
  • 1
Konstantin Yovkov
  • 62,134
  • 8
  • 100
  • 147
  • this is called [variance](https://msdn.microsoft.com/en-US/library/ee207183.aspx) – Binkan Salaryman Jun 19 '15 at 09:02
  • Thanks! I was misled by the compiler message focussing on the generic types. Also, I thought the compiler would understand that `Double` is `Comparable` and that interfaces would be handled differently than class inheritance for generics. I still think that the Java logic of using the `extends` keyword in generics for describing that I expect a type `S`that *implements* and interface is a little off. Do I miss something here? Does it make sense to *extend and interface* with generics? – madison54 Jun 19 '15 at 09:05
  • Yes, `extends` in Generics is used for both classes and interfaces. – Konstantin Yovkov Jun 19 '15 at 09:06
  • for best results use `S extends Comparable super S>` – newacct Jun 19 '15 at 18:39