1

I have a generic type K, and I want to verify whether K implements interface Comparable or not. Here is my code:

public class HashMapVectorSimilarity<K> {
    static public <K> double calculateSimilarity(HashMap<K, Double> hashMap1, HashMap<K, Double> hashMap2) {
        if (Comparable.class.isAssignableFrom(K)) {//
                  }
       }

But the code doesn't work. I don't want to limit all K to implementing Comparable. I have another TreeMapVectorSimilarity class already. If K implements interface Comparable,I will return the result using TreeMapVectorSimilarity class instead.

How do you think I can solve this problem? Thanks.

CyberPlayerOne
  • 3,078
  • 5
  • 30
  • 51
  • 1
    `public class HashMapVectorSimilarity` and compiler will check it for you. Also I highly recommend to get familiar with java syntax at first. :) – Leri Mar 14 '14 at 08:07
  • Thanks but I want the type K can also be something doesn't implement Comparable interface. – CyberPlayerOne Mar 14 '14 at 08:09
  • @SANDSOFTIME Then you will have to pass `Class` as a parameter to the function (or to the constructor and store it as a field; see the link in my answer for options and examples here), but you should ask yourself if a `HashMapVectorSimilarity` actually makes sense for a non-`Comparable` object (it very well might, but make sure you consider it). – Jason C Mar 14 '14 at 08:16

3 Answers3

4

If you want to enforce that only types K can be used that implement Comparable, you can check it at compile time:

public class HashMapVectorSimilarity<K extends Comparable<K>> {
  ...
}

This is easiest and probably best.

If you want a runtime check, you cannot do it the way you wrote, because of type erasure. The way generics work in Java is that the compiler checks all the types, but erases them, so they're not available at runtime.

So if you want to have the runtime type available, you need to pass in a Class object explicitly:

    static public <K> double calculateSimilarity(
        HashMap<K, Double> hashMap1, HashMap<K, Double> hashMap2, Class<K> clazz) {
      if (Comparable.class.isAssignableFrom(clazz)) {
        ...
      }
    }

Or you could pass clazz in to the constructor and store it inside the object.

Thomas
  • 174,939
  • 50
  • 355
  • 478
0

As mentioned by Leri change your code to:

public class HashMapVectorSimilarity<K extends Comparable<K>> {
}
Community
  • 1
  • 1
Harmlezz
  • 7,972
  • 27
  • 35
0

You can't really do this without specifically storing a Class<K> at some point (e.g. pass it as a parameter to the method, or pass it to the constructor and hold it in a field); see Get generic type of class at runtime for some options there.

If the hash maps aren't empty you could hack it by getting one of the keys and grabbing its class, but I highly recommend against this.

The best solution is to ensure that the type implements the interface you are interested in, if possible, e.g.:

public class HashMapVectorSimilarity<K extends Comparable<K>> {
    ...
}

If you aren't willing to limit all K to implementing Comparable<K>, though, your next best bet is to pass the class itself as a parameter somewhere -- although in that case, you should really ask yourself if your HashMapVectorSimilarity actually makes sense for non-Comparable types.

Community
  • 1
  • 1
Jason C
  • 38,729
  • 14
  • 126
  • 182