2017-10-25 23 views
6

Chcę utworzyć mapę komparatorów w następujący sposób, ta mapa będzie używana do zapewnienia komparatora dla każdego rodzaju klasy.Jak używać generycznych w mapie Komparatora, aby uniknąć ostrzeżeń

Jak mogę zamienić rodzajowy? w deklaracji mojej mapy, aby mieć pewność, że zawsze mam ten sam typ Klasy w kluczu i wartości mojej mapy (komparatory)?

Chcę również, aby zmniejszyć liczbę ostrzeżeń

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()); 
     } 
    }); 
    ... 
} 
+0

Dlaczego nie wystarczy użyć prostej klasy bez leków generycznych? Rozumiem, że otrzymasz ostrzeżenie od kompilatora. Możesz użyć adnotacji '@SuppressWarning (" niezaznaczone ")', aby zignorować to ostrzeżenie. – SMA

+0

rozważ, że możesz użyć @SuppressWarning ("niezaznaczone") przed nazwą metody. – marco

+1

Dlaczego nie chcesz, aby każda klasa implementowała Komparator? –

Odpowiedz

4

Aby zmniejszyć ilość ostrzeżeń można umieścić owijkę wokół mapie porównawczym (like in this answer).

Dzięki temu rozwiązaniu musisz rzucić ten typ tylko raz w swojej klasie otoki (i otrzymać tylko jedno ostrzeżenie). Podczas dzwonienia otrzymasz klasę otoki, nie otrzymasz ostrzeżenia i nie będziesz musiał rzucać wartości.

Przykład:

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 
    } 
} 
+1

Lepiej jest umieścić Mapę w klasie 'MyTypeSafeMap' i użyć zdefiniowanej metody' put', aby umieścić komparatory w bloku statycznym. – Alex

+0

@Alex "Nowa" mapa znajduje się w klasie MyTypeSafeMap. Mam tylko starą mapę na zewnątrz, aby pokazać oba przypadki. Ale zmienię nazwy zmiennych, aby były bardziej przejrzyste. –

+0

@ BenjaminSchüller MyTypeSafeMap jest lepszy niż stary. Czy masz pomysł, jak dodać ograniczenie w deklaracji mapy (Mapa , Komparator >), aby użyć tego samego typu? coś podobnego Mapę , Komparator > – Aguid

Powiązane problemy