Из-за стирания типа вы не можете использовать стандартный оператор instanceof
. Канонический подход состоит в том, чтобы передать сам класс или его экземпляр куда-нибудь.
Затем вы можете использовать отражение, чтобы проверить тип экземпляра:
private Class<V> clazz; // somehow this gets set
public boolean containsValue(Object value){
if(clazz.isInstance(value)){
// safe:
V temp = (V) value;
}
Вы также можете проверить дерево наследования, используя Class.isAssignableFrom
:
if(clazz.isAssignableFrom(value.getClass())){
// safe:
V temp = (V) value;
}
Обратите внимание, что это гарантирует, что это типобезопасное приведение, но не требует, чтобы типы были одинаковыми, например, V
может быть Number
, но value
может иметь тип Integer
.
Что касается получения clazz
, вы можете применить его в своем конструкторе:
public class MyMap<K,V>{
private final Class<V> clazz;
public MyMap(Class<V> clazz){
this.clazz = clazz;
}
...
И ваш инициализатор для класса может выглядеть примерно так:
MyMap<Integer,String> foo = new MyMap<Integer,String>(String.class);
Обычно я поддерживаю передачу типа в конструкторе для такого рода вещей и помечаю поле как final
, так как семантика и ограничения не позволят вам изменить это поле, что является разумным, поскольку экземпляр обычно полагается на гарантии времени компиляции, которые предполагают, что параметры типа не изменены.