Ответ 1
Вы не можете получить его из экземпляра, потому что в генераторах Java параметр типа доступен только во время компиляции, а не во время выполнения.
Это называется стиранием типа. Более формальное определение предоставляется в JLS.
Возможный дубликат:
Получить общий тип java.util.List
У меня есть карта, и я хочу получить тип T из экземпляра этой Карты. Как я могу это сделать?
например. Я хочу сделать что-то вроде:
Map<String, Double> map = new HashMap<String, Double>();
...
String vtype = map.getValueType().getClass().getName(); //I want to get Double here
Конечно, в API нет такой функции getValueType().
Вы не можете получить его из экземпляра, потому что в генераторах Java параметр типа доступен только во время компиляции, а не во время выполнения.
Это называется стиранием типа. Более формальное определение предоставляется в JLS.
Если ваш Map
является объявленным полем, вы можете сделать следующее:
import java.lang.reflect.*;
import java.util.*;
public class Generic {
private Map<String, Number> map = new HashMap<String, Number>();
public static void main(String[] args) {
try {
ParameterizedType pt = (ParameterizedType)Generic.class.getDeclaredField("map").getGenericType();
for(Type type : pt.getActualTypeArguments()) {
System.out.println(type.toString());
}
} catch(NoSuchFieldException e) {
e.printStackTrace();
}
}
}
Вышеприведенный код напечатает:
class java.lang.String
class java.lang.Number
Однако, если вы просто имеете экземпляр Map
, например. если он передан методу, вы не можете получить информацию в это время:
public static void getType(Map<String, Number> erased) {
// cannot get the generic type information directly off the "erased" parameter here
}
Вы можете захватить подпись метода (опять же, используя отражение, как в моем примере выше), чтобы определить тип erased
, но это никуда не денется (см. ниже).
Edit:
Следует отметить комментарии BalusC ниже. Вам действительно не нужно это делать; вы уже объявили тип карты, поэтому вы не получаете больше информации, чем у вас уже есть. См. Его ответ здесь.
Хотя были даны правильные ответы, есть еще одна альтернатива, которая еще не указана. В основном поля и методы - это не единственные места, где может существовать общая информация типа: объявление суперкласса также содержит эту информацию.
Это означает, что если ваша Карта фактически является подтипом типа:
class MyStringMap extends HashMap<String,String> { }
тогда можно определить общие параметры типа, которые были использованы, вызвав "getGenericSuperclass" (на "instance.getClass()" ), а затем обратившись к назначенным фактическим параметрам типа. Он действительно задействован, так как нужно перемещаться по иерархии типов, чтобы обеспечить правильную привязку параметров к Map (может быть aliased и т.д.), Но это можно сделать. И именно так "супер токен" используется для передачи общего объявления типа:
new TypeToken<Map<String, Double>>() { }
который используется многими фреймворками Java (Jersey, Guice, Jackson и многие другие)
Проблема заключается в том, что, хотя это позволяет определить номинальные типы экземпляра, оно работает только в том случае, если существует фактический не общий подкласс универсального типа, и я не знаю, как обеспечить выполнение этого требования (вызов код может показаться странным, что для этой цели он должен создать несколько поддельный Подкласс класса).