简体   繁体   中英

How to Use Generics in a map of Comparator to avoid warnings

I want to create a map of comparators as following, this map will be used to provide the comparator for each kind of class.

How can I replace the Generic ? in the declaration of my map to be sure that I have always the same Class type in key and value of my map (comparators )?

I want also to reduce the number of warnings

 private static final Map<Class<?>, Comparator<?>> comparators = new HashMap<>();

static {
    comparators.put(Identifiable.class, new Comparator<Identifiable>() {
        @Override
        public int compare(Identifiable o1, Identifiable o2) {
            return o1.getId().compareTo(o2.getId());
        }
    });
    comparators.put(MyClass.class, new Comparator<MyClass>() {
        @Override
        public int compare(EIntersection o1, EIntersection o2) {
            return o1.getRef().compareTo(o2.getRef());
        }
    });
    ...
}

To reduce the amount of warnings you can put a wrapper around your comparator map ( like in this answer ).

With this solution you have to cast the type only once in your wrapper class (and get only one warning). When calling get on your wrapper class you don't get a warning and don't have to cast the value.

Example:

private static final Map<Class<?>, Comparator<?>> oldComparatorsMap = new HashMap<>();  
private static final Map<Class<?>, Comparator<?>> newComparatorsMap = new MyTypeSafeMap();

static {
    oldComparatorsMap.put(String.class, new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            return o1.compareTo(o2);
        }
    });
    oldComparatorsMap.put(Integer.class, new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1.compareTo(o2);
        }
    });
    newComparatorsMap.put(String.class, new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            return o1.compareTo(o2);
        }
    });
    newComparatorsMap.put(Integer.class, new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            return o1.compareTo(o2);
        }
    });
}

public static void main(String[] args) {

  Comparator<String> c1 = (Comparator<String>)oldComparatorsMap.get(String.class); // Warning for every call on get with a cast

  Comparator<String> c2 = newComparatorsMap.get(String.class); // No warning here and no cast

}

static class MyTypeSafeMap {
  private static final Map<Class<?>, Comparator<?>> innerComparatorsMap = new HashMap<>();

  public <T> void put(Class<T> key, Comparator<T> value) {
    innerComparatorsMap .put(key, value); 
  }

  public <T> Comparator<T> get(Class<T> key) {
    return (Comparator<T>) innerComparatorsMap .get(key); // Only one warning here
    // we know it's safe, but the compiler can't prove it
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM